Home > Back-end >  Function calling function in c
Function calling function in c

Time:05-02

I'm trying to write the “plus2” and “plus3” functions that implement the functions, respectively, and are defined as follows.

f is a function such that expression (x) (y) should result in the value of x y.

g is a function such that expression (x) (y) (z) should result in the value of x y z. Here, x, y, z are integers.

#include <functional>
#include <iostream>
std::function<int(int)> plus2(int n) {
  return [n](int x) { return x   n; };
}
std::function<int(int)> plus3(int f(int), int n) {
  return [f, n](int x) { return f(n)   x; };
}
int main() {
  std::cout<<plus2(1)(2)<<" "<<plus3(1)(2)(3);
  return 0;
}

OUTPUT should be: 3 6

I get an error

too few arguments to function ‘std::function<int(int)> plus3(int (*)(int), int)’

Function plus2 works fine. Could you explain me where I'm making mistake in function plus3?

CodePudding user response:

Function plus2 works fine.

Because plus2 is a function that expects 1 parameter and returns a function that expects 1 parameter.

plus3 on the other hand is a function that expects 2 parameters. You cannot call it with only one parameter. You can turn it into a function that expects one parameter and returns a callable that returns a callable.

I suppose this is just an exercise to learn lambdas, because otherwise I see no reason to write the functions like this. At least you should use auto return type to avoid unnecessary conversion to std::function (*):

#include <iostream>

auto plus3(int n) {
    return [n](int a) { return [b=a n](int c){ return b c;} ;};
}

int main(int argc, char* argv[]){    
    std::cout << plus3(1)(2)(3);
}

(*): std::function is not the type you should use whenever you want to pass a callable around. Rather it is the type to be used when you need one type that can store any kind of callable. std::function uses type erasure to achieve that. If you do not need that then you do not need std::function.

CodePudding user response:

It looks like you are practicing the subject of currying in functional programming (Currying - Wikipedia).

If you want to write plus3 as a curried function you can do the following (no change in plus2):

#include <functional>
#include <iostream>

auto plus2(int n) {
    return [n](int x) { return x   n; };
}

auto plus3(int n) {
    return [n](int m) {
        return [n, m](int x) { return x   n   m; }; };
}

int main() {
    std::cout << plus2(1)(2) << " " << plus3(1)(2)(3);
    return 0;
}

CodePudding user response:

plus3 should take an int and produce a function.
It should not take a function and an int.

The resulting function should take an int and then proceed as plus2.

It's a nice touch to reuse plus2:

std::function<std::function<int(int)>(int)> plus3(int n) {
    return [n](int x) { return plus2(n x); };
}

Slightly more readable with a type alias:

using int_to_int = std::function<int(int)>;
std::function<int_to_int(int)> plus3(int n) {
    return [n](int x) { return plus2(n x); };
}

and now you can generalize:

template<size_t n>
auto plus(int x)
{
    return [x](int y) { return plus<n-1>(x y); };
}

template<>
auto plus<1>(int x) { return x; }

int main() {
    std::cout << plus<2>(1)(2) << std::endl << plus<4>(1)(2)(3)(4) << std::endl;
}

  • Related