
On 4/11/08, shunsuke <pstade.mb@gmail.com> wrote:
Giovanni Piero Deretta wrote:
I prefer prefix, because result_of expression and function-call expression are in sync: result_of<T_plus(int, int)>::type r = plus(1, 2); I thought 'typeof_' was too long. Anyway we should decide by majority vote.
+1 for separate namespace. If that is controversial, +1 for typeof_ instead.
After all, I will follow Boost.Fusion (and other Boost libraries). Ditto `X_` prefix.
the 'functional' namespace?
Though I'm not sure what you mention, curry/bind is not can-do-everything. It must capture arguments by-copy.
use ref/cref if you want capture by reference. In almost all my use cases, it is fine to capture the object by copy (usually a function object).
Egg developement started to remove ref/bll::make_const from pipable functions. That's the forwarding problem!
I know :). Anyways, my idea was that the '_' syntax could capture by reference by default (i.e. only downward funargs)..
BTW, on a completely unrelated topic: it would be nice if bind/lambda allowed to specify the default capture behaviour, like C++0x lambdas (I think that with proto this wouldn't be hard to do).
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 was imprecise: foo(bar(_,_))
Actually corresponds to:
lazy(foo)(protect(lazy(bar)(_1, _2))) (); // we are calling it!
The point is that unlike lambda expressions, '_' does not cause the full expression to be a lazy expression (up to the protect) I'll try to be more clear later.
I perhaps understand what you mention. You are trying to express *un*lambdification by using `_`. Am I right?
hum. I think that the authors of fc++ can explain it way better than I can: http://www.cc.gatech.edu/~yannis/fc++/currying.html
I tend to think it should be expressed by using nesting-levels. E.g. `foo(bar(_,_))` can be translated into `nest1(foo)(nest2(bar)(_1_(_1), _1_(_2)))` // \() -> foo(\(x,y)->bar(x,y)) (or a better syntax sugar.)
hargh! :P parse error!
I'm still lost. Why not `lazy_ex(is_less_non_curriable)(_, 10)(7)` ? (Assume `lazy_ex` supports "non-numbered placeholder".)
Almost the same, except that you would need to wrap the call to lazy_ex around protect(). If lazy_ex were to apply protect implicitly would be exaclty the same. BTW, I do not consider non-numbered placeholders necessary, I was just mimicking FC++ syntax.
The protect is important, you do not need the full power of lambda (ie.e function composition) , so you want to stop 'lambdification' immediately. This is why a better name would be a lazy_simple :)
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.
BTW, bll::unlambda should be used instead of protect?
Yes! have never understood exactly what protect is useful for. I, wrongly, use often protect when I mean unlambda. In this case I definitely meant unlambda!
But, strictly speaking, it seems impossible to detect whether a FunctionObject is ResultOf conforming or Lambda conforming. We need C++0x Concept. (has_sig_template or has_result_template is not enough.)
Uh? Why? doens't your result_of work seamlessy with both the sig and result_of protocol? where is the problem?
After some thoughts, "If has_sig_template is true, use Lambda protocol. Otherwise, use ResultOf protocol." may be a good solution.
This is what I do in my result_of replacement and so far has worked flawlessy.
(But I'm not sure it is a better way to apply a heavy patch into a stable library.)
This is a much needed one!
Never tried it, but I'm quite sure that the phoenix lambda syntax also let you return lambdas:
auto always = lambda[ lambda(_a = _1)[ _1 ] ];
auto always_10 = always(10);
assert(alsways_10() == 10);
should work (modulo modifying phoenix to work with rvalues). Disclaimer: I haven't tryed it! But even if it doesn't work with phoenix, it shouldn't be terribly hard to make this syntax work.
I expect Proto-professionals will invent cool syntax for nestN. :-)
for me nestN is completely opaque. I should sit down and trace step by step what it does. I'll probably have one of those 'A-ah!' moments :). Another thing that bothers me with nestN is that it seems that there is an hard coded limit (i.e. the max N in _N_) on the number of nesting levels and also you have to specify the nesting level explictly instead of being implicit in the expression.
Probably nestN should sleep until the day will come.
Agree.
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; } 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 // more fun! auto always_the_sum = lambda[ curry1(lambda[arg1])(arg1 + arg2) ]; auto always_10 = always_the_sum(4, 6); assert(always_10() == 10); (functional programming is fun) BTW I've implemented the above with just an hour of work with lambda adaptors (with plain c++03) and it worked! The best thing is it is completely result_of compatible (you can express the type 'always' with result_of). Anyways, all of this is just for toying with c++ and not really relevant with egg. You have clarified all my doubts on your library . I hope to write the final review done for tonight (spoiler: accepted modulo a mini review only for the documentation). -- gpd