0

I am a beginner in C++ and want to do simple example of composite function. For example, in MATLAB, I can write

a = @(x) 2*x
b = @(y) 3*y
a(b(1))

Answer is 6

I searched following questions. function composition in C++ / C++11 and Function Composition in C++

But they are created using advanced features, such as templates, to which I am not much familiar at this time. Is there a simple and more direct way to achieve this? In above MATLAB code, user does not need to know implementation of function handles. User can just use proper syntax to get result. Is there such way in C++?

** Another Edit:**

In above code, I am putting a value at the end. However, if I want to pass the result to a third function, MATLAB can still consider it as a function. But, how to do this in C++?

For example, in addition to above code, consider this code:

c = @(p,q) a(p)* b(q)  %This results a function
c(1,2)
answer=12

d = @(r) a(b(r))
d(1)
answer=6

function [ output1 ] = f1( arg1 )
val = 2.0;
output1 = feval(arg1,val)
end

f1(d)
answer = 12

In this code, c takes two functions as input and d is composite function. In the next example, function f1 takes a function as argument and use MATLAB builtin function feval to evaluate the function at val.

How can I achieve this in C++?

Community
  • 1
  • 1
34usdh34
  • 1
  • 2
  • 3
    Probably something similar like [c++ lambda functions](http://en.cppreference.com/w/cpp/language/lambda)? What exactly does `@(x)` do in MATLAB? – πάντα ῥεῖ Aug 01 '16 at 19:00
  • I still don't understand `fun1`. It looks like it takes an argument `c`, ignores that argument, and unconditionally *returns* `a`. You then *call* `fun1`, passing `1`, which should be ignored, but somehow the answer you get is 2, not `@(x) 2*x` or `a`. WTF? – zwol Aug 01 '16 at 20:15
  • Function composition is an operation that takes two functions and returns another function. I don't see any function composition in the matlab code, can you show me where it hides? – n. m. could be an AI Aug 01 '16 at 20:31
  • @zwol Edited the question. – 34usdh34 Aug 02 '16 at 12:28
  • @n.m. Edited the question with modified definition – 34usdh34 Aug 02 '16 at 12:28
  • Your description _still_ seems inconsistent with your code. As far as I can tell, you are still calling `c` with *numbers* as arguments, not functions. Is there something about MATLAB which I don't know, that causes `c(1,2)` not to be a call of `c` with arguments 1 and 2? – zwol Aug 02 '16 at 12:31
  • I have edited my answer to include translations of `c` and `d` according to what it *appears to me* they do, which does *not* involve passing functions as arguments to other functions. (That *can* be done in C++, too, but without a MATLAB case that you actually care about, I think it would only confuse you to show you how.) – zwol Aug 02 '16 at 12:37
  • @zwol I further edited the question. Now function `f1` takes a function as input and uses builtin `feval` to evaluate. In the `d = @(r) a(b(r))`, I am implicitly passing `b` into `a`. – 34usdh34 Aug 02 '16 at 13:19
  • "I am implicitly passing `b` into `a`" -- Wait, does MATLAB do the thing R does where functions can access their arguments as *unevaluated* expressions? – zwol Aug 02 '16 at 13:25
  • I believe so (others can correct me if I am wrong.). Because, `f1` takes argument `arg1` as unevaluated expression, same goes with `a(b(r))`. – 34usdh34 Aug 02 '16 at 15:05

4 Answers4

4

Perhaps I'm misunderstanding your question, but it sounds easy:

int a(const int x) { return x * 2; }
int b(const int y) { return y * 3; }

std::cout << a(b(1)) << std::endl;

Regarding your latest edit, you can make a function return a result of another function:

int fun1(const int c) { return a(c); }

std::cout << fun1(1) << std::endl;

Note that this returns a number, the result of calling a, not the function a itself. Sure, you can return a pointer to that function, but then the syntax would be different: you'd have to write something like fun1()(1), which is rather ugly and complicated.

ForceBru
  • 43,482
  • 10
  • 63
  • 98
4

How about:

#include <iostream>

int main(int, char**)
{
    auto a = [](int x) { return 2 * x; };
    auto b = [](int y) { return 3 * y; };

    for (int i = 0; i < 5; ++i)
        std::cout << i << " -> " << a(b(i)) << std::endl;

    return 0;
}
Nik Bougalis
  • 10,495
  • 1
  • 21
  • 37
2

C++'s evaluation strategy for function arguments is always "eager" and usually "by value". The short version of what that means is, a composed function call sequence such as

x = a(b(c(1)));

is exactly the same as

{
  auto t0 = c(1);
  auto t1 = b(t0);
  x  = a(t1);
}

(auto t0 means "give t0 whatever type is most appropriate"; it is a relatively new feature and may not work in your C++ compiler. The curly braces indicate that the temporary variables t0 and t1 are destroyed after the assignment to x.)

I bring this up because you keep talking about functions "taking functions as input". There are programming languages, such as R, where writing a(b(1)) would pass the expression b(1) to a, and only actually call b when a asked for the expression to be evaluated. I thought MATLAB was not like that, but I could be wrong. Regardless, C++ is definitely not like that. In C++, a(b(1)) first evaluates b(1) and then passes the result of that evaluation to a; a has no way of finding out that the result came from a call to b. The only case in C++ that is correctly described as "a function taking another function as input" would correspond to your example using feval.

Now: The most direct translation of the MATLAB code you've shown is

#include <stdio.h>

static double a(double x)           { return 2*x; }
static double b(double y)           { return 3*y; }
static double c(double p, double q) { return a(p) * b(q); }
static double d(double r)           { return a(b(r)); }

static double f1(double (*arg1)(double))
{ return arg1(2.0); }

int main()
{
    printf("%g\n", a(b(1)));  // prints 6
    printf("%g\n", c(1,2));   // prints 12
    printf("%g\n", d(1));     // prints 6
    printf("%g\n", f1(d));    // prints 12
    printf("%g\n", f1(a));    // prints 4
    return 0;
}

(C++ has no need for explicit syntax like feval, because the typed parameter declaration, double (*arg1)(double) tells the compiler that arg1(2.0) is valid. In older code you may see (*arg1)(2.0) but that's not required, and I think it makes the code less readable.)

(I have used printf in this code, instead of C++'s iostreams, partly because I personally think printf is much more ergonomic than iostreams, and partly because that makes this program also a valid C program with the same semantics. That may be useful, for instance, if the reason you are learning C++ is because you want to write MATLAB extensions, which, the last time I checked, was actually easier if you stuck to plain C.)

There are significant differences; for instance, the MATLAB functions accept vectors, whereas these C++ functions only take single values; if I'd wanted b to call c I would have had to swap them or write a "forward declaration" of c above b; and in C++, (with a few exceptions that you don't need to worry about right now,) all your code has to be inside one function or another. Learning these differences is part of learning C++, but you don't need to confuse yourself with templates and lambdas and classes and so on just yet. Stick to free functions with fixed type signatures at first.

Finally, I would be remiss if I didn't mention that in

static double c(double p, double q) { return a(p) * b(q); }

the calls to a and b might happen in either order. There is talk of changing this but it has not happened yet.

zwol
  • 135,547
  • 38
  • 252
  • 361
0
int a(const int x){return x * 2;}
int b(const int x){return x * 3;}
int fun1(const int x){return a(x);}

std::cout << fun1(1) << std::endl; //returns 2

This is basic compile-time composition. If you wanted runtime composition, things get a tad more involved.

Altainia
  • 1,347
  • 1
  • 7
  • 11