
On Fri, Apr 11, 2008 at 12:45 PM, shunsuke <pstade.mb@gmail.com> wrote:
Giovanni Piero Deretta wrote:
I tend to think the way using ref is not so bad. :-) `_1 < ref(m) && _2 < m` will be cumbersome in C++0x.
Not sure what you means here. The syntax I had in mind was:
lambda_ref[ _1 < m ]
which would be the same as:
lambda[ _1 < ref(m) ]
or
lambda[_1 < cref(m) ]
i.e. it would do perfect forwarding.
I hear that
`_1 < ref(m) && _2 < m` will be: int m_ = m; [&m, m_](int a, int b){ return a < m && b < m_ }; in C++0x. `m_` is needed to copy. IMO, placeholder expression seems more beautiful than C++0x expression. :-p
For simple expressions, definitely! Also, I have lost hope of C++0x lambdas being useful when they dropped polymorphic lambdas. May be a future revision...
I think only the outmost lazy function knows when *un*lambdification should be performed.
I think that I still I haven't explained my self: you need to unlambda the immediate expression that uses placeholders. I want no Lambda, I just want to express simple generalized a-la FC++ currying using what just I have: boost.lambda.
FC++ currying slightly confuse me. Again, that is not currying. :-(
I have read many different definitions of currying and partial applications. For what I can infer, formally the curry operation transforms a function of multiple arguments to an unary higher order function: given int f(int a, int b); // (int int) -> int and a curry operator Callable<Callable<int(int)>(int)> curry( Callable<int(int, int)> ) ; // ((int, int) -> int) -> int -> int -> int then f_curryed = curry(f) has type Callable<int(int)> f_curryed(int); // int -> int -> int In haskell all functions are automatically curryed (unless you explicitly ask for tuples). in other languages you can to implement both currying and partial application via closures. So the terms become a little fuzzy. I have no formal functional programming training, so I have gotten all my terminology from FC++ where currying and partial application are practically the same thing. In fc++, if you have a function object of type: int divide(a, b) It is already curryied a-la haskel, so you can write: auto divide_10_by = divide(10) This can also be written: auto divide_10_by = divide(10, _) This syntax is useful if you do not want to partially apply only the first arguemnt: auto divided_by_10 = divide(_, 10) I think that to do this with only currying you need some argument juggling to swap order (or a plain old lambda). FC++ calls the operation that transform a nary function in a function that accept the '_' placeholder, generalized currying, or (as it, IIRC, doesn't have a plain curry operator), just currying. In FC++ all function objects are in practice always curryied. So, yes, it is a misnomer, but in practice, at least in c++, the difference is not that great, and the distinction not very useful.
FWIW, nestN can be used with result_of, because its expression contains only function-calls.
You can express nested lambdas using curry. [I will keep using both the lambda[] syntax and optionally lazy functions because I find it more readable, just substitute it with 'unlambda' and apply magic 'lazy' pixie dust where necessary :)]
let's define (in pseduo c++0x syntax var args and new function syntax).
template<class F, class C> struct closure1 { F f; C c;
template<typename Args...> auto operator ()(Args... args) -> decltype(f(c, args...)) { return f(c, args...); }
};
// this is actually a function object template<class F, class C> closure<F, C> close1(F f, C c) { closure<F, C> result = { f, c}; return result; }
Egg uses this to implement curryN. See: egg/detail/bind_left1.hpp.
Of course. But I think that the documentation states that curryN is implemented in term of nest. I was going for the other route, that is, nest is not necessary and you can just curry nested lambdas to get the effect of the phoenix lambda(...)[] syntax and still be result of compatible.
Now you can express this
auto always = lambda[ lambda(_a = _1 + 7)[ _1 ] ];
as:
auto always = lambda[ close1(lambda[ arg1 ], arg1) ];
or, obviously,
// another function object template<class F> auto curry1(F f) -> decltype(lambda[ close1(f, _1) ]) { return lambda[ close1(f, _1) ]; }
auto always = curry1( lambda[arg1] );
or, just for the heck of it:
auto always = lambda[ curry1(lambda[arg1])(arg1) ]; // needlessy convoluted
How about: auto always = close1(close1, _1);
sure, but my point is writing lambdas that can return lambdas (see the "needlessy convoluted" note) :). Now, back on writing the review. -- gpd