
Giovanni Piero Deretta wrote:
Just two things:
- using result_of requires the 'round lambda syntax' which means that I can't easily use them in mpl expressions (I can't put mpl::placeholders in place of argument types). Of course I can round trip via boost.FunctionTypes but is very verbose (and probably slower).
- having to specify ::type requires prefixing the expression with typename in templates if the type is dependent.
It is not necessarily egg job to fix this, but it would be nice to have this. It is ok if I have to specify static_ in addition.
Ok. That return_of will be a candidate for it.
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.
I want to define PipableFunctionObject without dependency on Egg library.
I appreciate this need, but IMHO it is not worth it. The pipable support library could be a single, self contained header.
I want to make this concept independent as "curried function" is. Also, in simple cases (e.g. arity is small, or perfect-forwarding is unneeded.), you can make PipableFunctionObject without Egg so that compile-time and runtime complexity can be removed.
ADL kicks in even for template argument types (i.e. namespace of template arguments are considered associated namespaces), so this works :
namespace egg { namespace pipable_support { struct pipable {};
template<typename T, typename T2> void operator |(T, T2); }; using pipable_support::pipable; } template<typename T = egg::pipable> struct my_fun_t {};
int main() { my_fun_t<> my_fun = {}; // statically initialized!
1|my_fun; }
No need for inheritance. There might also be other tricks.
It seems what Egg does. Instead of a tag type(pipable), Egg uses a metafunction result_of.
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!
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.
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? 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.)
I think so, expect that I'm not sure if the result of compose is still a lambda expression. Of course, using a plain _1 here is pointless, but with more complex expressions it make more sense:
map(range, lazy(multiply)(_1, 5) | is_less(_, 100));
If you were to use _1 instead of _ you would need to use protect:
map(range, lazy(multiply)(_1, 5) | protect(lazy(is_less)(_, 100)));
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. BTW, bll::unlambda should be used instead of protect?
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. (But I'm not sure it is a better way to apply a heavy patch into a stable library.) If Daniel has really succeeded to implement it, I will follow it. BTW, bll/result_of.hpp just provides result_of specializations for Lambda functors. That is ok.
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. :-) Probably nestN should sleep until the day will come. FWIW, nestN can be used with result_of, because its expression contains only function-calls. Regards, -- Shunsuke Sogame