2

std::bind is sometimes described as "partial application". Any reasons why when all parameters of a function are bound, the function itself isn't applied?

For example, the following code prints nothing.

#include <functional>
#include <iostream>
using namespace std;
using namespace std::placeholders;

void f(int a,string b) {cout << a << b << endl;};
int main() {
  bind(bind(f,1,_1),"Hi!");
  return 0; 
}

Is there a way to write a bind variant that can apply the function when all parameters are fixed?

--Update--

I understand from the responses now that std::bind is not exactly partial application. So, on the second part of the question, how can I write something like std::bind but does partial application. I know bind(bind(f,1,_1),"Hi!")() will call the final 0-ary function and return the result value (printing 1Hi in the example). Is it possible to do template programming to call the function call operator () in the terminal case of bind?

In other words, is it possible to write a function bind1:

template< class R, class F, class... Args >
bind1( F f, Args... args )

, such that when std::is_placeholder<T>::value == 0 for each member of args, bind1() can, in addition to what std::bind() does, call the operator()?

thor
  • 21,418
  • 31
  • 87
  • 173
  • 10
    Bind 1 of 3 arguments, get a function of 3-1=2 arguments. Bind 2 of 3 arguments, get a function of 3-2=1 argument. Bind 3 of 3 arguments, get a function of 3-3=0 arguments. Having `bind` sometimes return a function object and sometimes return something else would be surprising, especially if you're creating the function so you can call it for its side effects. – user2357112 Jan 21 '14 at 02:15
  • 3
    I don't think so. Bind does what the name says. It binds. It does not execute. You just get a functor with less parameters. This is a simple, non-technical, description of what is happening. – TimDave Jan 21 '14 at 02:21
  • time to decide what your question is... do you really need an answer for your last question? – Karoly Horvath Jan 21 '14 at 02:22
  • Yes, it would be convenient. In other languages like Haskell, you can partially apply a parameter to a function, do this again and again,..., when all parameters are applied, you get a value. I would think something similar would be useful. – thor Jan 21 '14 at 02:33
  • Prelude> let f x y = x + y ; Prelude> (f 1) 2 ; 3 – thor Jan 21 '14 at 02:34
  • 1
    I guess that's why `bind` is called `bind` and not `curry`. Also, you should read the documentation on [`std::bind`](http://en.cppreference.com/w/cpp/utility/functional/bind) again - you're using it incorrectly. You want `bind(bind(f,1,_1),"Hi!")`. – Casey Jan 21 '14 at 02:59
  • @Casey Thanks. I've corrected the bind usage issue you pointed out. I guess my question is now more about the second part. How to have something like bind that can do the partial application (or `curry` as you phrased it) like in other languages. – thor Jan 21 '14 at 03:31

2 Answers2

2

A function with no arguments is just a value in Haskell. You don't call it, you just use it. Since there are no side effects, there is no observable difference.

In OCaml there are simply no parameter-less functions, to get something like that you need to add a dummy unit argument.

Not so in C++. C++, unlike Haskell and OCaml, maintains clear difference between f and f(). bind gives you the former because you can always turn it into the latter by adding (). You can write your own wrapper for bind that does just that quite easily. Going the other way around would be a tad more difficult.

Here's a possible implementation of such wrapper:

#include <functional>
#include <utility>
#include <iostream>

template <typename T>
struct is_noargs_callable {
  private:
    typedef char(&yes)[1];
    typedef char(&no)[2];

    template<typename U> 
      static yes test(decltype((std::declval<U>())())*);

    template<typename> 
      static no test(...);

  public:
    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

template <typename T>
struct is_noargs_callable<T()> {
  static const bool value = true;
};

template <typename T>
struct is_noargs_callable<T(...)> {
  static const bool value = true;
};

template <typename T>
auto call_me_if_you_can(T t) -> typename std::enable_if<is_noargs_callable<T>::value, decltype(t())>::type
{
  return t();
}

template <typename T>
auto call_me_if_you_can(T t) -> typename std::enable_if<!is_noargs_callable<T>::value, T>::type
{
  return t; 
}

template <typename... Args>
auto apply(Args&&... args) -> decltype(call_me_if_you_can(std::bind(args...))) {
  return call_me_if_you_can(std::bind(args...));
}

// testing

void foo(int a, int b, int c) { std::cout << "foo(" << a << "," << b << "," << c << ")";  }

int main ()
{
  using namespace std::placeholders;
  std::cout << "zero : " ; apply(foo, _1, _2, _3); std::cout << " : " ; apply(foo, _1, _2, _3)(1,2,3); std::cout << std::endl;
  std::cout << "one  : " ; apply(foo, 1, _1, _2); std::cout << " : " ; apply(foo, 1, _1, _2)(2,3); std::cout << std::endl;
  std::cout << "two  : " ; apply(foo, 1, 2, _1); std::cout << " : " ; apply(foo, 1, 2, _1)(3); std::cout << std::endl;
  std::cout << "three: " ; apply(foo, 1, 2, 3);  std::cout << " : "; /* nothing to test here */ std::cout << std::endl;
}

However, killing the difference between f and f() just in this one place does not IMHO contribute to the overall consistency of C++ programming. If you don't like the distinction, kill it everywhere (or just use you a Haskell for great good).

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • Thanks @n.m. I think the apply here is more like a strict version of partial application, and std::bind is more of a lazy version of it. So both are consistent in its own way. In that sense, it's kind of weird that the lazy version is default in c++. Probably easier to implement I guess. – thor Feb 12 '14 at 21:58
1

No sources for this, just my opinion.

The reason that wasn't done is because there is no reason to do it. If you know all of the input to the function, just call it.

And if you were doing something with templates that resulted in this, you would need to write all of the code consistently anyway. A special case here would only require a special case somewhere else.

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • I suppose I am thinking about other languages like Haskell or OCaml, where you get a value in the end when you fix all parameters: Prelude> let f x y = x + y ; Prelude> (f 1) 2 ; 3 – thor Jan 21 '14 at 02:37
  • Just curious, will above generate a type inconsistency for variadic programming? – thor Jan 21 '14 at 02:42
  • @TingL: Haskell has no side effects, so it doesn't matter whether the function is evaluated at the point where all of the parameters are bound or later when the value is used. In fact, Haskell has lazy evaluation, so functions usually aren't evaluated at the point where all of their values are bound. You don't see lazy evaluation in the REPL, becuase the print statement that forces the function to be evaluated almost immediately, before the next chance you have to input anything into the REPL. I don't know anything about OCaml (which I think does have side effects). – Ken Bloom Jan 21 '14 at 03:36
  • @KenBloom I think other languages that are not lazy also have partial application, maybe lisp??. I guess am more interested in having such in C++. For my purposes, I do not need the side effect part `cout << ...`. bind is the first to come to my mind. – thor Jan 21 '14 at 03:50