
On Tuesday, August 23, 2011 10:59:36 PM Eric Niebler wrote:
On 8/23/2011 5:21 PM, Mathias Gaunard wrote:
On 08/23/2011 11:15 PM, Mathias Gaunard wrote:
On 08/23/2011 09:38 PM, Eric Niebler wrote:
After playing around with functional languages, I've come to envy how easy they make it to curry functions. Call a 2-argument function with 1 argument and you get a function that takes 1 argument. Pass another argument and it evaluates the function. Simple. In contrast, C++ users have to use binders, which are not as nice.
On a lark, I implemented a wrapper that turns any TR1-style function object into a "curryable" function object (attached). Successive function call invocations bind arguments until enough arguments are bound to invoke the wrapped function. With it you can do the following:
curryable<std::plus<int> > p; auto curried = p(1); int i = curried(2); assert(i == 3);
Is there any interest in such a thing?
It could be argued that Phoenix actors should be doing this.
I also asked a lot of time ago for an easy function to turn a pfo into a phoenix actor, which I think would make phoenix much more ubiquitous.
assuming that function was called lazy, and Phoenix did currying automatically, you could do
int i = (lazy(std::plus<int>)(1) + 4)(3)
Sorry, this should have been int i = (lazy(std::plus<int>())(1) + 4)(3) of course.
I would rather extend and reuse bind for that.
Could you explain this? I'm guessing that lazy(std::plus<int>()) creates a binary function, and that lazy(std::plus<int>())(1) binds the first argument and returns a unary function. But what does it mean to add an integer to a unary function? That doesn't make sense to me.
And I remember why Phoenix doesn't do currying: that's because that only works with monomorphic function objects.
What only works with monomorphic functions?
Detecting and propagating monomorphism could be nice though. It could eventually provide better error messages, faster compilation times, and automatic currying on monomorphic function objects.
What do monomorphic functions have to do with this? My currying code works with polymorphic functions.
I also fail to see why currying should only work on monomorphic objects. However, the problem comes with function objects having operator() overloads with different arity. Another problem I couldn't solve yet is how to decide which overload gets curryied or not. Consider: struct foo { void operator()(int); void operator()(int, int); }; curryable<foo> f; auto curried = f(1); // To curry or not to curry, that is the question TBH, i haven studied your code yet, Eric. would be cool if solvd these problems. Additionally I second the call to integrte it into phoenix. Using bind and placeholders is just not elegant enough. There even is a feature request about it in trac: https://svn.boost.org/trac/boost/ticket/5541
Sorry if I'm being dense. It's pretty late over here.
And here it is too early ... will report back after studying the code. All in all i think such a thing would be very useful!