
I'm attaching some comments after a not-so-brief reading of the egg documentations. I've started the review a while ago, so some of the comments (especially those about static initialization) might be obsolete after the long discussion I had with the author in another thread, but Shunsuke Sogame might want to respond again for those that missed that thread. This is not yet a complete review, I want to spur further discussion on this library (especially on the documentation) before providing a final review. Finally I would like to encourage others to review this library (no reviews yet and we are in the second week!) because it provides some extremely needed functionalities. -- gpd

Giovanni Piero Deretta wrote:
I'm attaching some comments after a not-so-brief reading of the egg documentations.
I've started the review a while ago, so some of the comments (especially those about static initialization) might be obsolete after the long discussion I had with the author in another thread, but Shunsuke Sogame might want to respond again for those that missed that thread.
This is not yet a complete review, I want to spur further discussion on this library (especially on the documentation) before providing a final review.
Finally I would like to encourage others to review this library (no reviews yet and we are in the second week!) because it provides some extremely needed functionalities.
I'm attaching the answers to your egg.txt. Regards, -- Shunsuke Sogame
=== Introduction
- "Egg what for?" (shouldn't it be "What is Egg for?"): why do I need to use the ugly BOOST_EGG_PIPABLE syntax? why doesn't the following syntax work?:
result_of_pipable<T_plus>::type const my_plus = {};
(As you pointed,) Those macros are unneeded in the case of stateless functions. So, I propose a new `static_` form: The adapting form in review version: result_of_curry2<F>::type const c = BOOST_EGG_CURRY2({}); // stateless is changed to a new `static_` form *without macros*: static_< result_of<T_curry2(F)> >::type const c = {{}}; How do you think about this new form?
Also, it seems that egg takes a lot of care to make sure that function objects are statically initialized, but they can't still be used in headers because of ODR. Egg should provide a solution to that (more to come).
I should consult the author of Boost.Proto.
- Notation:
Please get rid of this notation. The double underscore syntax hurts my eyes :). Also it is very hard to have to always refer to this section when reading the documentation. The last four entries are obvious enough, and so is decltype. For the rest you should find a different, self explicative notation.
Because the document of FunctionAdaptor section is going to be simplified, I think I can remove most of them.
=== Quick Start
- "Problems of function templates"
"take by reference" shouldn't it be pass by reference?
Will fix.
1. "a function template is not an object". Provide an example of the prolem. Showing how hard is to use 'make_filtered' with bind would be nice.
Ok.
3. "Unintentional ADL". It is claimed (in the solution) that egg solves the problem of unintended adl by making make_filtered an object.
Be aware that gcc performs ADL even on function objects.
Which version of gcc?
- "Binding functions"
"boost::result_of isn't used for now". Why?
Because of a bug described in the `egg::result_of_` section.
Higher Order functions.
I do not see how 'pipable' is an higher order function. Here it is just a function adaptor. In fact make_filtered is already an higher order function (i.e. a function that takes/returns another function as a parameter/return value, in this case the filtering predicate).
Ah, I see, you mean that pipable takes a function and returns another function which is pipable. The intent seems lost in the MACRO_NOISE.
Anyways, the section name is misleading. Just call it pipable functions. BTW, 'pipable' really sounds wrong to me (but I'm not a native english speaker, so YMMV :) ).
If you rename the section, you should of course put the paragraph about lazy on its own section.
Ok.
The description of lazy supposes that the reader is familiar with boost lambda which is a non trivial library. Of course egg is not exactly a beginner library, so it might be expected.
The visual distinction between make_filtered and make_Filtered might not be caught immediately. May be change the name? Also, I do not like this convention of having the lazy variant having an uppercase letter in the middle. Is this just a random example or is meant to be a useful convention? (BTW, I think that egg documentation should have a good section about function object naming conventions).
I don't find a convertion for lazy and unlazy functions yet. I hope the authorities help me.
Also I do not like the T_* convention to name function types. I liked best the old op_* convention.
LexicallyTypedObject concept is not restricted to FunctionObjects. "T_" is short of "typeof". This concept is a workaround for "missig decltype" in C++03.
- Getting initializers
"As mentioned before, the static initialization is important". Why? You still do not explain it.
Click "before".
Also, what if I want to put my funciton object in an header file and do not want to risk ODR violation?.
Should we state that "Use EGG_CONST everywhere." ? Anyway I should consult Eric.
- Object generators
It is completely un-obvious what are you trying to explain here. Even clicking on the link about object generators doesn't really enlighten me much: if the name 'always' parallels the mpl counterpart it should be a function that always returns the same value. But why you call it 'always_return' and not just 'always'?
Ah, I see, you later name the actual object 'always'. But why the adapted class (or would be better to call it 'facaded'?) was postifixed _result? If it were just a metafunction to compute the result type I would understand, but the 'call' method makes it something more than an mpl metafunction.
always_result means a return type of always.
I completely fail to see the parallel with object generators. What kind of magid does exactly generator do?
Probably I should write an example which compares egg::generator with a hand-made code.
"function_facade might remind you of boost::iterator_facade". Yes, so what? You do not explain how it works here. Why should I prefer function_facade to poly? What are the advantages of either solutions?
poly builds a stateless POD function object type, whereas function_facade cannot be POD, but can have user-defined constructors.
- Partial application.
How partial application described here is different than the one presented in 'lazy'? (except that as far as I understand, 'lazy' is implemented in term of nestN).
The introduction of 'lazy' might be too early.
"bind expressions my be less readable. nestN offers a better syntax"
egg::nest2(plus)(5, egg::nest2(_1_(_1))(_1_(_2), _0_(_1))) (i6)(minus, i7);
Is that a joke?!?!? :) I use both boost.bind and lambda.bind extensively and while I might not like the syntax, at least is clear what it does. the _N_(_M) syntas not only is *extremely* ugly, but I have absolutely no idea of what are you trying to do! Please explain.
The haskel-like lambda syntax doesn't help. I can barely read simple haskel expressions, certainly not nested lambdas. I expect most C++ programmers (even very sophisticate ones) wouldn't either.
nestN returns a function which returns a function which returns a function... Probably I should change the notation into C++0x lambda expression?
Anyways, this certainly shouldn't be in the quick start section (if it has to be shown at all and not remain as an implementation detail of the library).
Ok.
You say that curryN can be implemented in term of nestN (?), but you do not explain what it does.
It seems bad that I am using haskell notation.
Fusing
Why should I use egg fusing/unfusing instead of the fusion provided ones (do they have other benefits/functionalities?
Egg can support stateful static-initialization.
=== Concepts:
- Lexically Typed: This is not really a concept (how would you express in ConceptC++? Can you write a C++03 concept check?). It is just a convention.
So it seems.
I find the prefix T_ extremely ugly. I preferred what I think egg used previously, i.e. the op_ notation.
This convention is not restricted to FunctionObjects. `T_` is short of "typeof". This convention is a workaound for "missing decltype" in C++03.
Even better would be to segregate function object types to their own namespace, a-la fusion or proto. (i.e. the functional namespace).
See this: namespace poost { namespace op { struct foo {}; } op::foo const foo = {}; namespace nested { namespace op { struct bar {}; } op::bar const bar = {}; void test() { op::foo my_foo = foo; // doesn't compile } } } Thus, I've rejected segregated-namespace-way.
- Pipable and Ambi: These concepts are intermixed and too fuzzy IMHO. All the details of Ambi and Pibable, should be collapsed on a simpler Pibaple concept
I made some efforts to define these concept. I believe this way is the simplest (for now).
(and BTW, Ambi is not a self descriptive name):
I will be happy if a better name for ambi is found in this review.
" A pipable function object 'f' is an unary polymorphic function object for which the expression 'x | f' is equivalent to f(x) ".
Making a function object pipable should just be a matter of deriving it from an (empty) egg::pipable, which would manifest the intention of the object to participate in pipelines.
I'm not sure it has an advantage over higer-order functions.
Oven should provide a free function operator| (that will be found via adl, and sfinae'd on is_base_and_derived<pibable, Rhs>).
Sorry, I couldn't understand this sentence. Why is Oven stated here?
Adapting function objects of arbitrary arity to make them pibable is really orthogonal. Lambda would works just fine, but egg could provide (if already doesn't)adaptors to add curriability functionality to a generic function object:
struct op_foo : curriable<op_foo> { typedef whatever result_type; template<class A1, class A2, class A3> result_type operator()(A1, A2, A3); } foo;
x | foo(_, 10, "bar");
Note that you need to explicitly mark the missing argument. And in principle you can have more than one missing argument:
f(_, 10, _)("baz", "bar");
Sorry, I couldn't understand this proposal. What does `x | foo(_, 10, "bar")` mean? Also, f(_, 10, _)("baz", "bar"); seems supported by egg::lazy.
- Major Function Object: this name is not descriptive. Make it Lambda Compatible Polymorphic Function Object.
A specific name should not be contained in this concept name so that MajorFunctionObject can support yet another lambda library.
Or better, modify boost.lambda so that any Polymorphic function object work with it (shouldn't be hard), so that we do not need an ad-hoc concept.
It seems hard.
- Static Function Object: again, you are mixing a concept, with pertains types, with restriction on object usages or initialization. I do not think that you can encode the fact that 'f' is statically initialized in a concept. Also, this 'concept' badly need a rationale!
I'm going to modify this concept. The "stateless" requirement will be added, and the static-initialization guarantee will be removed. Do you think it is right?
- Little Function: initially I didn't like this concept, but now I see its utility. Still, the name isn't descriptive. What about Primitive Function Object?
I will consider it. BTW, it was originally called BabyFunction.
- result of tutorial: this really doesn't belong here. boost.result_of documentation should just be corrected (may be by replacing it with this section).
I agree. Boost.ResultOf is nearly undocumented.
=== Forwarding strategies
- What are these for? Provide rationale and use cases in the introduction. It is very hard to follow the expressions in the 'valid expressions' boxes. In general this whole chapter is very obscure. I think you are trying to be too formal.
- by_perfect: you should explain explicitly what perfect forwarding is (I see the link to 'the forwarding problem', but a small introduction should be necessary here).
I think moderate users don't need to read this section. But I admit that by_perfect should be roughly explained using an easy example.
What is 'aI' in the 'Notation' paragraph? Ah, I see, is the I'th 'a' in an argument list. I do not understand your juggling of 'a's and 'b's.
This is because by_perfect instantiates both const and non-const overload function declarations while performing overload resolution. It might be too formal.
- by_ref: you say that by ref offers larger arity, you should make it explicit that MAX_LINEAR_ARITY is larger than MAX_ARITY.
Ok.
- Writing you strategies: why should I want to write my own strategy? What can I do exactly?
See the Eric's request below.
In valid expression you introduce apply_little, but you do not document it anywhere it seems (its use seems obvious, though).
It isn't placed in Valid expressions table?
Where is the custom forward strategy in the valid expression box? How should be interpreted.
Sorry, I couldn't understand this question.
What magic does FUNCTION_PREAMBLE do? Why I need it? It is very ugly.
Mainly because it makes egg::function be a model of PolymorphicFunctionObject. If interested in the implementation, see egg/detail/function_preamble.hpp.
In the paragraph 'specializing function<>' what is function, and why should I want to specialize it? clicking on it just bring us back to the paragraph!
In general, is specializing the forwarding strategy just worth it?
IIRC, while reviewing Boost.Functional/Forward, Eric requests a forwarding way which can be translated into: BOOST_EGG_FUNCTION_CALL_OPERATOR( (by_perfect)(by_perfect)(by_perfect)(by_perfect)(by_perfect) (by_ref)(by_ref)(by_ref)(by_ref)(by_ref) , const) So, I've added support of user-defined strategy.
=== Function builders
- function: finally we find the function class! I object in another class in boost called function. What about function_adaptor?
This is not an adaptor. IIRC, Boost.Phoenix also uses "function".
- function_facade. Why should I use function_facade instead of function? It seems that it supports stateful funciton objects. Do they work with 'function'?
If you need user-defined constructors, egg::function is not usable.
BTW, do you want to encourage stateful function objects? Since I learned 'bind' I have never again written a stateful function object.
I rarely use Boost.Bind and Boost.Lambda in production code.
It would be great if egg had a way to express the result type of bind (in fact I think that lazy does exactly that).
If a Boost.Lambda expression is simple, it is feasible. The full support would be challenging work.
"it can be considered a port of callable". I do not know what 'callable' is. Please provide a link/reference.
Click 'callable'.
- generator. I finally *think* I understand what generator does. In practice it helps you write constructors a-la functinal languages. The user must implement the deduction rules via mpl expressions and generator provides the boilerplate code to actually instantiate the object. Still it is not yet clear to me how does it work. Some more examples and prose are wellcome.
Ok.
- implicit. "Implicit adds implicit conversion support to a cast from function". What does that means? What are the use cases?
It automatically passes initialized types to cast functions.
- poly. "poly is a port of detail::funciton family which is secretely contained in boost.accumulator". This doesn't really tell me anything. It is at best a footnote and yet is the first line of the description.
Will be moved to "See also" section.
This is Yet Another Way to build polymorphic function objects (the others are 'function' and 'function_facade'). Isn't this too much for such a "simple" need? I appreciate the syntax conveniences provided by 'funciton' and 'poly', but I do not think that the 'intellectual overhead' of having to understand the different syntaxes is worth it. (as a side note, I do not really understand what function_facade add, even at the syntax level),
egg::function builds a stateful pod function. egg::function_facade builds a stateful function which has user-defined constructors. egg::poly builds a stateless pod function.
- static_. "builds a pod function object from a default constructible one". How does this work? The adapted function object must be a POD, so what does static_ adds? What is the magic here? I think that it must be exposed, or else it would be hard to understand when and why static_ is needed.
I'm going to slighly change the definition of `static_` as StaticFunctionObject concept definition is changing. I had overlooked the power of `static_` before you pointed. (I will add more elaborate description.) Thanks, gdp.
- variadic. As you says, Is just a shortcat to fuse. It is really necessary to add it?
Yes in my experience. Once the new static_ form is introduced, poly + unfuse would be more cumbersome without this.
=== Function Adaptors
- ambiN. I have already commented on the name and on the purpose of this function on the Ambi concept definition.
- Compose. This is what pipealbe should be in my opinion! :) Extremely useful. I can't parse the 'valid expressions' section at all!
Thanks to you, valid expression tables are going to be very simplified. All the macro expressions will be moved to a small "Stateful static initialization" section.
Please, do not use the infix notation in the example section, expecially as you do not have introduced it yet. A simple 'compose(increment, decrement)' will be more than enough.
Ok.
- curryN "The curry family turn Function Objects into curried ones." Please explain what curry means (not that I know what it means exactly :)). Which is a shame, because it is a very useful facility.
I will do my (english) best.
Arguments except for the last one are captured by-copy. When you need to capture by-reference, pass arguments using boost::ref." Why the last one is an exception (I guess your use case, and mine too, is to pass ranges and containers as last arguments)
No, it is not range problem. Currying is "binding", per se. It must copy arguments to make an intermidate FunctionObjects. The last argument is not needed to be copied fortunately.
In the example, mabye 'my_minus_base' would be a better name for the struct?
I prefer prefix, but I'm sure I don't know english well. :-)
The examples simply show the two parameters for curried being passed immediately. It might seem that curry simply offers a different syntax for function calling (which in a sense is true). Maybe show the classic example of 'add_5' being applied to all elements of a container via std::transform.
I agree.
- Uncurry. Uh? What is this useful for? BTW, a more useful facility would be the ability to traverse all objects stored in a curry closure (is closure the right term?), like the undocumented boost.bind apply_visitor.
I couldn't find boost.bind apply_visitor.
- Fix. Now, this is really something that needs detailed description :). Maybe You should start with the problem of writing a recursive anonymous functions. (how can it call itself when it doesn't have a name?). Do not use boost.lambda, at least not in the first example, first show a simple hand written function object (which wouldn't be anonimous, but whatever :P).
I will consider it. (In fact, I just wanted to show the power of C++. :-)
Why do I need to use 'lazy' in the lambda expression? And what does lazy(_1) means? Ah, maybe boost.lambda doesn't allow invoking operator() on a placeholder (never tried), and this is just a workaround. You should specify it though.
Ok.
Also, is lazy itself 'optionally lazy' (it behaves specially when its parameter is a placeholder?). I do not see anything relevant in lazy description.
No, lazy is not 'optionally lazy'. Using egg, "lazy function" can be made in one shot. 'optionally lazy' is a little confusing, IMO.
- fuse/unfuse. Again, aren't the adaptors provided by fusion enough?
It can support stateful static initialization.
- indirect. Nothing useful (or even useless) to say here :)
- lazy. Useful, 'nuf said. I would also like to have optionally lazy function objects, but it seems that I'm the only one who likes them :).
In fact, I know another one who likes them.
- memoize. An use case would be very useful.
I must learn more to find many examples. :-)
- mono. I have never needed this, but I understand that it might be useful sometimes.
IIRC, Dan Marsden's Boost.Traversal makes use of one.
- nestN. This is still very very obscure to me. The more I read the description the more confused I become. I understand that the problems are nested lambda expressions, but I do not understand how your soultion work, what the syntax is and why it must be so complicated
A comparison between "bind" and "nestN" has been requested, so I will add some explanations of details.
(did you see how phoenix handles the problem via local variables to lambda?)
Because Egg is not "yet another lambda library", I'm not sure it should provide some cool syntax. If reviewers regard it as an inadequate component, I will simply remove nestN from Egg. BTW, how can we write nested lambda using phoenix?
- perfect. Recently a forwarding library has been added to boost. Does 'perfect' add anything?
It can support stateful static initialization and can be used with Boost.Lambda.
- pipable. I have already commented on pipable in the concept section.
- regular. I understand the need for this, but wouldn't it better to just fix lambda. Not that it would be easy...
I wish I could fix it.
(Also I think that boost.bind and maybe even tr1::bind has the same problem, is that right?).
IIRC, a FunctionObject Boost.Bind returns is not DefaultConstructible. I should note it.
- return_. Does this just do the equivalent of implicit cast?
No. This is a higher-order function which modifies return types.
- tagged. I have never needed strong typedefs for function objects. What are your use cases?
See egg/protect.hpp.
=== Function objects
- adapted_to. Shouldn't this be adapted_from?
It can be regarded as "adapted_function_object_to_base_function_object".
- always/identity/apply. Obvious and generally useful.
- bll_N. Is this just an alias for lambda placeholders? why i can't just use _N and boost::lambda::placeholderN_type?
bll_N is a model of LexicallyTypedObject so that you don't need to remember the name "placeholderN_type".
In the 'valid expressons' it states 'polymorphic boost::lambda::_N'. What does 'polymorphic' refers to here?
It means that bll_N is a model of PolymorphicFunctionObject.
- X_construct. Hum, doesn't boost already has this functionality elsewhere?
AFIAK, no if you need the perfect forwarding.
- construct_braced{1,2}. Eh? what is this for?
- construct_variadic. Same as above.
egg::generator needs this to initialize pod types.
- get. I think that fusion is going to provide all its algorithm/intrinsics as function objects in the functional namespace, so this might be redundant.
If so, it can be removed.
- pack. Is this just like make_tuple but with perfect forwarding? (i.e. no need for cref/ref).
Yes. Also, this is a FunctionObject.
=== Utilities
- expr. It seems interesting, but the example doesn't show anything significative. What does it exaclty do? Ah, maybe I see it, I was missing the BOOST_AUTO. Is type erasure performed using boost.function?
Yes. boost.function is used.
Doesn't having to specify the signature partially defeats the purpose? Why can't I just do:
BOOST_AUTO(f, unfuse(fuse(_1 + _2)))
and keep my lovely polimorphic-nes? i.e. would it be possible for egg to (optionally) register all its type with boost.typeof?
Egg could do, but I think it is nearly impossible for Boost.Lambda.
Of course the user would be responsible for registering its own function objects.
I can't imagine users register their function objects.
- Infix. I like it! Since I saw it on FC++ I have always wanted to replicate the syntax.
... But I do not like how you implement it. I want explicit conformance. You avoid the problem of having a catch-all operator^ by segregating it in the infix namespace, but the using is still very risky. The user should have to use an adaptor (infixable? hopefully not unfixable ;) ) to get to use this syntax. I also want to use it in lambdas, so operator^ should be registered with this library... ah, yes, and the | pipe operator too :).
'infixable' seems cool. I will try it.
- bll/result_of.hpp Nice, but let's just fix lambda!
I agree. Hence, bll/result_of.hpp is written to be independent from Egg.
=== Configuration
nothing to say here.
=== Workarounds.
- result_of_. hopefully result_of can be fixed by the time egg becomes part of boost.
I also hope so.
- detect_result_type. Same thing for BOOST_MPL_HAS_XXX_TRAIT_DEF
- CONST. I wouldn't call this a workaround. ODR violation can be a real problem. I know that the gcc team is working on linker changes to detect ODR violations. Anyways, I do not see how CONST help with ODR violations. For example, what should I do if I want to put my 'filtered' function in an header file? Please provide an example.
Should we oblige the use of CONST? I should consult Eric and Boost.Proto.
- OVERLOADED. Please, describe the problem. I think that when a workaround for a compiler bug is present in the interface, it should be explained to the user what the problem is and how the workaround fix it (for example see the 'dummy<int>' idiom and its explaination in 'enable_if' documentation)...
Ok
... ok, I've read the linked discussion on comp.lang.c++ and I understand that nobody really understand the problem :). So, yes, I'm ok with the current (lack of) explaination.

On Wed, Apr 9, 2008 at 11:16 AM, shunsuke <pstade.mb@gmail.com> wrote:
Giovanni Piero Deretta wrote:
I'm attaching some comments after a not-so-brief reading of the egg documentations.
I'm attaching the answers to your egg.txt.
And here are my replies to some of your answers.
=== Introduction
- "Egg what for?" (shouldn't it be "What is Egg for?"): why do I need to use the ugly BOOST_EGG_PIPABLE syntax? why doesn't the following syntax work?:
result_of_pipable<T_plus>::type const my_plus = {};
(As you pointed,) Those macros are unneeded in the case of stateless functions. So, I propose a new `static_` form:
The adapting form in review version: result_of_curry2<F>::type const c = BOOST_EGG_CURRY2({}); // stateless is changed to a new `static_` form *without macros*: static_< result_of<T_curry2(F)> >::type const c = {{}};
How do you think about this new form?
Much better, but I do not particulary like the static_ name (expecially because of the trailing '_'). Statically_initialized is too long, so if you can't come up with anything better and shorter, I can live with static. Btw, can you explain me (again, please :P) why result_of<T_curry2(F)> >::type const c = {{{}}; isn't enough? I guess I should see static_ implementation. What about collapsing static_ and result_of in a single class, and allowing arbitrary composition: apply<compose, apply<compose, my_fun1, my_fun2>, my_fun3>::type c = {{}}; The apply name is already taken by MPL, but maybe something of the sort.
- Notation:
Please get rid of this notation. The double underscore syntax hurts my eyes :). Also it is very hard to have to always refer to this section when reading the documentation. The last four entries are obvious enough, and so is decltype. For the rest you should find a different, self explicative notation.
Because the document of FunctionAdaptor section is going to be simplified, I think I can remove most of them.
Great!
3. "Unintentional ADL". It is claimed (in the solution) that egg solves the problem of unintended adl by making make_filtered an object.
Be aware that gcc performs ADL even on function objects.
Which version of gcc?
AFAIK all of them: namespace a { struct foo_t {}; struct bar_t { void operator()(foo_t){}; } bar; }; int main() { a::foo_t foo; bar(foo); } This compiles at least with gcc-4.1.3 and gcc-3.3.6 (it doesn't with comeau online) The biggest problem is of course is that gcc fails to compile this: namespace a { struct foo_t {}; struct bar { }; }; void bar(...); int main() { a::foo_t foo; bar(foo); } I.e. ADL finds even non callable entities! Comeau online compiles it cleanly.
- "Binding functions"
"boost::result_of isn't used for now". Why?
Because of a bug described in the `egg::result_of_` section.
Ah, now understand why I'm missing some documentation details! the documentation doesn't always clearly show which words are links. for example in my browser result_of_ is not visually distinguished from the rest of the paragraph. I do not know if it is a problem of my browser of you need to fix your CSS.
The description of lazy supposes that the reader is familiar with boost lambda which is a non trivial library. Of course egg is not exactly a beginner library, so it might be expected.
The visual distinction between make_filtered and make_Filtered might not be caught immediately. May be change the name? Also, I do not like this convention of having the lazy variant having an uppercase letter in the middle. Is this just a random example or is meant to be a useful convention? (BTW, I think that egg documentation should have a good section about function object naming conventions).
I don't find a convertion for lazy and unlazy functions yet.
I do not either, other than puting them in a 'lazy' namespace. This is one of the reasons I like optionally lazy function objects :).
Also I do not like the T_* convention to name function types. I liked best the old op_* convention.
LexicallyTypedObject concept is not restricted to FunctionObjects. "T_" is short of "typeof". This concept is a workaround for "missig decltype" in C++03.
What about using the prefix 'typeof_' or a postfix '_type'? I really dislike that uppercase T. Maybe even a postfix _t would be more than enough.
- Getting initializers
"As mentioned before, the static initialization is important". Why? You still do not explain it.
Click "before".
Right, missed the link. Probably this part should go in an advanced section or at least an had-hoc section on static initialization. Certainlin not in the quick start.
- Object generators
It is completely un-obvious what are you trying to explain here. Even clicking on the link about object generators doesn't really enlighten me much: if the name 'always' parallels the mpl counterpart it should be a function that always returns the same value. But why you call it 'always_return' and not just 'always'?
Ah, I see, you later name the actual object 'always'. But why the adapted class (or would be better to call it 'facaded'?) was postifixed _result? If it were just a metafunction to compute the result type I would understand, but the 'call' method makes it something more than an mpl metafunction.
always_result means a return type of always.
sure, but it also contains the body of 'always' (i.e. the call member), so it is a misleading name.
"bind expressions my be less readable. nestN offers a better syntax"
egg::nest2(plus)(5, egg::nest2(_1_(_1))(_1_(_2), _0_(_1))) (i6)(minus, i7);
Is that a joke?!?!? :) I use both boost.bind and lambda.bind extensively and while I might not like the syntax, at least is clear what it does. the _N_(_M) syntas not only is *extremely* ugly, but I have absolutely no idea of what are you trying to do! Please explain.
The haskel-like lambda syntax doesn't help. I can barely read simple haskel expressions, certainly not nested lambdas. I expect most C++ programmers (even very sophisticate ones) wouldn't either.
nestN returns a function which returns a function which returns a function... Probably I should change the notation into C++0x lambda expression?
That would probably help a little. Much more prose (like a step by step analisys of what that expression means) would be much better.
I find the prefix T_ extremely ugly. I preferred what I think egg used previously, i.e. the op_ notation.
This convention is not restricted to FunctionObjects. `T_` is short of "typeof". This convention is a workaound for "missing decltype" in C++03.
I know, I just find the syntax ugly.
Even better would be to segregate function object types to their own namespace, a-la fusion or proto. (i.e. the functional namespace).
See this:
namespace poost { namespace op { struct foo {}; }
op::foo const foo = {};
namespace nested { namespace op { struct bar {}; } op::bar const bar = {};
void test() { op::foo my_foo = foo; // doesn't compile } } }
Thus, I've rejected segregated-namespace-way.
uh? ... void test() { poost::op::foo my_foo = foo; // it compiles! } Seems a very simple fix (and arguably the right thing in the first place!)
- Pipable and Ambi: These concepts are intermixed and too fuzzy IMHO. All the details of Ambi and Pibable, should be collapsed on a simpler Pibaple concept
I made some efforts to define these concept. I believe this way is the simplest (for now).
(and BTW, Ambi is not a self descriptive name):
I will be happy if a better name for ambi is found in this review.
" A pipable function object 'f' is an unary polymorphic function object for which the expression 'x | f' is equivalent to f(x) ".
Making a function object pipable should just be a matter of deriving it from an (empty) egg::pipable, which would manifest the intention of the object to participate in pipelines.
I'm not sure it has an advantage over higer-order functions.
Less intellectual overhead :). I need to know less things to appreciate what 'pipable' means. Concept should be as simple as possible IMHO. (you can of course add "... but not simpler" :) )
Oven should provide a free function operator| (that will be found via adl, and sfinae'd on is_base_and_derived<pibable, Rhs>).
Sorry, I couldn't understand this sentence. Why is Oven stated here?
I meant Egg of course. What I wanted to say is: Egg provides a templated operator| in egg namespace. There is a single implementation for this operator and is: namespace pibable_ { struct pipable {}; // ADL hook template<typename Lhs, typename Rhs> typename boost::lazy_enable_if<bost::is_base_and_derived<pipable, Rhs>, boost::result_of<Rhs(Lhs&)> >::type operator|(Lhs& lhs, Rhs rhs) { return rhs(lhs); } template<typename Lhs, typename Rhs> typename boost::lazy_enable_if<bost::is_base_and_derived<pipable, Rhs>, boost::result_of<Rhs(const Lhs&)> >::type operator|(const Lhs& lhs, Rhs rhs) { return rhs(lhs); } } Any unary function object that wants to model the pipable concept must derive from pipable_::pipable. This will trigger ADL and will find the operator | when necessary. (In c++0x of course you would put operator| in the global namespace and make it a template function constrained on the (non auto) concept Pipable) This of course only work with unary callable entities. to make a non-unary entity unary, apply the appropriate curry/bind grease :). This will also get rid of the need for Ambi. As an extension (I'm not proposing it, it is just for the sake of discussion), '|' could be a synonym for compose (IIRC it is spelled '$' in haskell): if lhs and rhs are callable entites (in practice you detect pipability): a | b is the same as: compose(b, a); else if only b is a callable entity: a | b is the same as compose(b, always(a)); else the expression is illegal. [IIRC in haskel values are in practice treated as nullary functions, so the use of 'always' here would mimic the functional comunity usage] This means that you can create pipelines of transforms: map(my_range, my_first_view|my_second_view) Would be the same as: map(my_range, compose(my_second_view, my_first_view)); or map(my_range, my_first_view) | protect(lazy(_1, my_second_view)) [where map returns a pair of transform_iterators]. As an alternative for the ugly protect + lazy, read further.
Adapting function objects of arbitrary arity to make them pibable is really orthogonal. Lambda would works just fine, but egg could provide (if already doesn't)adaptors to add curriability functionality to a generic function object:
struct op_foo : curriable<op_foo> { typedef whatever result_type; template<class A1, class A2, class A3> result_type operator()(A1, A2, A3); } foo;
x | foo(_, 10, "bar");
Note that you need to explicitly mark the missing argument. And in principle you can have more than one missing argument:
f(_, 10, _)("baz", "bar");
Sorry, I couldn't understand this proposal. What does `x | foo(_, 10, "bar")` mean?
hum, let me see, in egg syntax it should be: compose(lazy(foo)(_1, 10, "bar), always(x)) but see below:
Also, f(_, 10, _)("baz", "bar"); seems supported by egg::lazy.
yes, the only difference is that the result is not a lambda expression (as if there was an implicit protect): see the difference between: lazy(foo)(lazy(bar)(_1, _2)); // ll::bind(foo, ll::bind(bar, _1)) and: lazy(foo)(protect(lazy(bar)(_1, _2))); // ll::bind(foo, protect(ll::bind(bar, _1))) with my syntax (actually this is lifted directly from the generalized currying in FC++), you could spell the latter: foo(bar(_,_)); // s this is important if egg were (as one would expect) to register its operator| with boost::lambda: map(my_range, _1 | lazy(is_less)(_1, 10)); // does not work! map(my_range, _1 | protect(lazy(is_less)(_1, 10))) ; //ok map(my_range, _1 | is_less(_, 10)); // also ok A nice name for the generalized curry operation is of course curry: auto is_less = curry(is_less_non_curriable); assert( is_less(_, 10)(7) == true ); This is trivially implementable with lazy + protect, but an ah-hoc implementation might be simpler and easier on the compiler (no need for full blown lambda support). Also, i spell the missing parameters '_' because that's what FC++ used, 'deferred' might also be a good name. What do you think?
- Major Function Object: this name is not descriptive. Make it Lambda Compatible Polymorphic Function Object.
A specific name should not be contained in this concept name so that MajorFunctionObject can support yet another lambda library.ù
Hum, the support hook shuld only be boost::result_of and its protocol.
Or better, modify boost.lambda so that any Polymorphic function object work with it (shouldn't be hard), so that we do not need an ad-hoc concept.
It seems hard.
I do not think so, in fact I think that there are patches around. On the other hand, I'm not the one doing it, so I shouldn't complain.
- Static Function Object: again, you are mixing a concept, with pertains types, with restriction on object usages or initialization. I do not think that you can encode the fact that 'f' is statically initialized in a concept. Also, this 'concept' badly need a rationale!
I'm going to modify this concept. The "stateless" requirement will be added, and the static-initialization guarantee will be removed. Do you think it is right?
I do not know if it is right, but I have only needed static initialization for stateless function objects. Others might have different experiences (and they should better speak now ;) ).
- Writing you strategies: why should I want to write my own strategy? What can I do exactly?
See the Eric's request below.
In valid expression you introduce apply_little, but you do not document it anywhere it seems (its use seems obvious, though).
It isn't placed in Valid expressions table?
yes, my fault, but those tables are almost unreadable to me, sorry :(
Where is the custom forward strategy in the valid expression box? How should be interpreted.
Sorry, I couldn't understand this question.
Me neither :). I have no idea of what I was asking.
=== Function builders
- function: finally we find the function class! I object in another class in boost called function. What about function_adaptor?
This is not an adaptor.
Hum, IMHO,yes. It is just adapt a class from the internal Minor function object convention to the external Major function object.
IIRC, Boost.Phoenix also uses "function".
Yes, I saw it too. But Phoenix is not a first class boost library yet :). when it will be reviewed, I'll make the same comment.
BTW, do you want to encourage stateful function objects? Since I learned 'bind' I have never again written a stateful function object.
I rarely use Boost.Bind and Boost.Lambda in production code.
Why not? I do all the time.
It would be great if egg had a way to express the result type of bind (in fact I think that lazy does exactly that).
If a Boost.Lambda expression is simple, it is feasible. The full support would be challenging work.
Agree. It would enought it just supported function composition (i.e. no overloaded operators).
"it can be considered a port of callable". I do not know what 'callable' is. Please provide a link/reference.
Click 'callable'.
Ah, I see. Again, the word here doesn't show up as a link untill i mouse over it.
- implicit. "Implicit adds implicit conversion support to a cast from function". What does that means? What are the use cases?
It automatically passes initialized types to cast functions.
could you provide an example?
Arguments except for the last one are captured by-copy. When you need to capture by-reference, pass arguments using boost::ref." Why the last one is an exception (I guess your use case, and mine too, is to pass ranges and containers as last arguments)
No, it is not range problem. Currying is "binding", per se. It must copy arguments to make an intermidate FunctionObjects. The last argument is not needed to be copied fortunately.
I figured it out later :).
In the example, mabye 'my_minus_base' would be a better name for the struct?
I prefer prefix, but I'm sure I don't know english well. :-)
Oh, well, me neither :P
- Uncurry. Uh? What is this useful for? BTW, a more useful facility would be the ability to traverse all objects stored in a curry closure (is closure the right term?), like the undocumented boost.bind apply_visitor.
I couldn't find boost.bind apply_visitor.
The actual name is visit_each (which I think is the protocol used by apply_visitor). There is some reference in bind/storage.hpp. The actual api is not documented, but I guess that the intent is that boost::visit_each(vistitor, bind-expression); should iterate on all arguments closed in the bind expression. Searching the boost mailing list reveals that bind_visitor has been broken for a while. I do not know if it is still true (I have never used it - yet).
- lazy. Useful, 'nuf said. I would also like to have optionally lazy function objects, but it seems that I'm the only one who likes them :).
In fact, I know another one who likes them.
:)
- mono. I have never needed this, but I understand that it might be useful sometimes.
IIRC, Dan Marsden's Boost.Traversal makes use of one.
I was missing the fact that it allows one to inspect the argument types.
- nestN. This is still very very obscure to me. The more I read the description the more confused I become. I understand that the problems are nested lambda expressions, but I do not understand how your soultion work, what the syntax is and why it must be so complicated
A comparison between "bind" and "nestN" has been requested, so I will add some explanations of details.
Thanks.
(did you see how phoenix handles the problem via local variables to lambda?)
Because Egg is not "yet another lambda library", I'm not sure it should provide some cool syntax.
well, at least readable :)
If reviewers regard it as an inadequate component, I will simply remove nestN from Egg. BTW, how can we write nested lambda using phoenix?
lambda[ for_each(_1, lambda(_a = _1)[ front(_a) += _1] )(range) [at least It should work, given appropriate definitions of for_each and front]
- bll_N. Is this just an alias for lambda placeholders? why i can't just use _N and boost::lambda::placeholderN_type?
bll_N is a model of LexicallyTypedObject so that you don't need to remember the name "placeholderN_type".
so now I have to remember two types instead of one :)
- construct_braced{1,2}. Eh? what is this for?
- construct_variadic. Same as above.
egg::generator needs this to initialize pod types.
Is it a general purpose utility of just an implementation detail?
Doesn't having to specify the signature partially defeats the purpose? Why can't I just do:
BOOST_AUTO(f, unfuse(fuse(_1 + _2)))
and keep my lovely polimorphic-nes? i.e. would it be possible for egg to (optionally) register all its type with boost.typeof?
Egg could do, but I think it is nearly impossible for Boost.Lambda.
Unless lambda registers its types of course. Anyways, It would be enough for me if this worked: BOOST_AUTO(foobar, compose(foo, bar));
Of course the user would be responsible for registering its own function objects.
I can't imagine users register their function objects.
Well, if an user wants to use typeof it needs to registers its types anyway. Enough for now. More comments to come. -- gpd

Giovanni Piero Deretta wrote:
(As you pointed,) Those macros are unneeded in the case of stateless functions. So, I propose a new `static_` form:
The adapting form in review version: result_of_curry2<F>::type const c = BOOST_EGG_CURRY2({}); // stateless is changed to a new `static_` form *without macros*: static_< result_of<T_curry2(F)> >::type const c = {{}};
How do you think about this new form?
Much better, but I do not particulary like the static_ name (expecially because of the trailing '_'). Statically_initialized is too long, so if you can't come up with anything better and shorter, I can live with static.
Ok.
Btw, can you explain me (again, please :P) why
result_of<T_curry2(F)> >::type const c = {{{}};
isn't enough? I guess I should see static_ implementation.
Because, in general, a higher-order function must support stateful functions. `static_` makes a default-constructed function object on-the-fly and forwards arguments to it. ( I call it "staticalization". ) Thus, `static_` can offer the static-initialization.
What about collapsing static_ and result_of in a single class, and allowing arbitrary composition:
apply<compose, apply<compose, my_fun1, my_fun2>, my_fun3>::type c = {{}};
The apply name is already taken by MPL, but maybe something of the sort.
I chose to minimize the set of names. static_< result_of<compose(result_of<compose(my_fun1, my_fun2)>::type, my_fun3)> >::type const c = {{}}; is enough. Users don't need to remember yet another metafunction `apply`. (result_of expression is a little combersome, though.) If you need static-initialization, wrap a result_of expression by `static_`. Isn't it simple? Also, it is only the outmost metafunction(i.e. static_) that knows when "staticalization" should be performed. Otherwise, all the metafunction have to perform "staticalization", which is wasteful.
The biggest problem is of course is that gcc fails to compile this:
namespace a {
struct foo_t {};
struct bar { }; };
void bar(...);
int main() { a::foo_t foo;
bar(foo); }
I.e. ADL finds even non callable entities! Comeau online compiles it cleanly.
I know this problem, which annoyed Boost.MPL. The problem is that `bar` is not a FunctionObject.
- "Binding functions"
"boost::result_of isn't used for now". Why?
Because of a bug described in the `egg::result_of_` section.
Ah, now understand why I'm missing some documentation details! the documentation doesn't always clearly show which words are links. for example in my browser result_of_ is not visually distinguished from the rest of the paragraph. I do not know if it is a problem of my browser of you need to fix your CSS.
I'm using CSS of boost. I hope it will be updated.
Also I do not like the T_* convention to name function types. I liked best the old op_* convention.
LexicallyTypedObject concept is not restricted to FunctionObjects. "T_" is short of "typeof". This concept is a workaround for "missig decltype" in C++03.
What about using the prefix 'typeof_' or a postfix '_type'? I really dislike that uppercase T. Maybe even a postfix _t would be more than enough.
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.
- Getting initializers
"As mentioned before, the static initialization is important". Why? You still do not explain it.
Click "before".
Right, missed the link. Probably this part should go in an advanced section or at least an had-hoc section on static initialization. Certainlin not in the quick start.
Ok.
always_result means a return type of always.
sure, but it also contains the body of 'always' (i.e. the call member), so it is a misleading name.
return_type_of_always might be better.
nestN returns a function which returns a function which returns a function... Probably I should change the notation into C++0x lambda expression?
That would probably help a little. Much more prose (like a step by step analisys of what that expression means) would be much better.
Ok.
Even better would be to segregate function object types to their own namespace, a-la fusion or proto. (i.e. the functional namespace).
See this:
namespace poost { namespace op { struct foo {}; }
op::foo const foo = {};
namespace nested { namespace op { struct bar {}; } op::bar const bar = {};
void test() { op::foo my_foo = foo; // doesn't compile } } }
Thus, I've rejected segregated-namespace-way.
uh? ... void test() { poost::op::foo my_foo = foo; // it compiles! }
Seems a very simple fix (and arguably the right thing in the first place!)
A result_of expression becomes long. This is a decision from my experince.
Making a function object pipable should just be a matter of deriving it from an (empty) egg::pipable, which would manifest the intention of the object to participate in pipelines.
I'm not sure it has an advantage over higer-order functions.
Less intellectual overhead :). I need to know less things to appreciate what 'pipable' means. Concept should be as simple as possible IMHO. (you can of course add "... but not simpler" :) )
I want to define PipableFunctionObject without dependency on Egg library.
I meant Egg of course. What I wanted to say is:
Egg provides a templated operator| in egg namespace. There is a single implementation for this operator and is:
namespace pibable_ {
struct pipable {}; // ADL hook
template<typename Lhs, typename Rhs> typename boost::lazy_enable_if<bost::is_base_and_derived<pipable, Rhs>, boost::result_of<Rhs(Lhs&)> >::type operator|(Lhs& lhs, Rhs rhs) { return rhs(lhs); }
template<typename Lhs, typename Rhs> typename boost::lazy_enable_if<bost::is_base_and_derived<pipable, Rhs>, boost::result_of<Rhs(const Lhs&)> >::type operator|(const Lhs& lhs, Rhs rhs) { return rhs(lhs); } }
Any unary function object that wants to model the pipable concept must derive from pipable_::pipable. This will trigger ADL and will find the operator | when necessary. (In c++0x of course you would put operator| in the global namespace and make it a template function constrained on the (non auto) concept Pipable)
I can't always use inheritance -- for stateful static initialization. Also, how can we make `_1+_2` pipable? A higher-order function is needed, after all.
This of course only work with unary callable entities. to make a non-unary entity unary, apply the appropriate curry/bind grease :). This will also get rid of the need for Ambi.
Though I'm not sure what you mention, curry/bind is not can-do-everything. It must capture arguments by-copy.
As an extension (I'm not proposing it, it is just for the sake of discussion), '|' could be a synonym for compose (IIRC it is spelled '$' in haskell):
A PipableFunctionObject supports '$' using `operator|=`. It might be different what you expect, though.
if lhs and rhs are callable entites (in practice you detect pipability): a | b is the same as: compose(b, a);
else if only b is a callable entity: a | b is the same as compose(b, always(a));
else the expression is illegal.
[IIRC in haskel values are in practice treated as nullary functions, so the use of 'always' here would mimic the functional comunity usage]
IMO, this seems to introduce unneeded complexity. "If 'a' is callable,... else if 'b' is pipable,... else if 'c' is a placeholder..." seems a bad switch statement.
This means that you can create pipelines of transforms:
map(my_range, my_first_view|my_second_view)
Would be the same as:
map(my_range, compose(my_second_view, my_first_view));
I understand it.
or
map(my_range, my_first_view) | protect(lazy(_1, my_second_view))
Sorry, I couldn't understand this expression.
Sorry, I couldn't understand this proposal. What does `x | foo(_, 10, "bar")` mean?
hum, let me see, in egg syntax it should be:
compose(lazy(foo)(_1, 10, "bar), always(x))
I understand it.
but see below:
Also, f(_, 10, _)("baz", "bar"); seems supported by egg::lazy.
yes, the only difference is that the result is not a lambda expression (as if there was an implicit protect): see the difference between:
lazy(foo)(lazy(bar)(_1, _2)); // ll::bind(foo, ll::bind(bar, _1))
I understand it.
and:
lazy(foo)(protect(lazy(bar)(_1, _2))); // ll::bind(foo, protect(ll::bind(bar, _1)))
with my syntax (actually this is lifted directly from the generalized currying in FC++), you could spell the latter:
foo(bar(_,_)); // s
I'm lost. How can I use this `foo(bar(_,_))` ?
this is important if egg were (as one would expect) to register its operator| with boost::lambda:
map(my_range, _1 | lazy(is_less)(_1, 10)); // does not work!
map(my_range, _1 | protect(lazy(is_less)(_1, 10))) ; //ok
map(my_range, _1 | is_less(_, 10)); // also ok
I'm lost again. Is `_1 | lazy(is_less)(_1, 10)` translated into `compose(lazy(is_less)(_1, 10), _1)` ?
A nice name for the generalized curry operation is of course curry:
BTW, strictly speaking, this is not a currying. This is a partial application.
auto is_less = curry(is_less_non_curriable);
assert( is_less(_, 10)(7) == true );
This is trivially implementable with lazy + protect, but an ah-hoc implementation might be simpler and easier on the compiler (no need for full blown lambda support). Also, i spell the missing parameters '_' because that's what FC++ used, 'deferred' might also be a good name.
What do you think?
I'm still lost. Why not `lazy_ex(is_less_non_curriable)(_, 10)(7)` ? (Assume `lazy_ex` supports "non-numbered placeholder".)
- Major Function Object: this name is not descriptive. Make it Lambda Compatible Polymorphic Function Object.
A specific name should not be contained in this concept name so that MajorFunctionObject can support yet another lambda library.u
Hum, the support hook shuld only be boost::result_of and its protocol.
Or better, modify boost.lambda so that any Polymorphic function object work with it (shouldn't be hard), so that we do not need an ad-hoc concept.
It seems hard.
I do not think so, in fact I think that there are patches around. On the other hand, I'm not the one doing it, so I shouldn't complain.
IIRC, Daniel Walker was trying it. 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.)
- Static Function Object: again, you are mixing a concept, with pertains types, with restriction on object usages or initialization. I do not think that you can encode the fact that 'f' is statically initialized in a concept. Also, this 'concept' badly need a rationale!
I'm going to modify this concept. The "stateless" requirement will be added, and the static-initialization guarantee will be removed. Do you think it is right?
I do not know if it is right, but I have only needed static initialization for stateless function objects. Others might have different experiences (and they should better speak now ;) ).
Ok.
=== Function builders
- function: finally we find the function class! I object in another class in boost called function. What about function_adaptor?
This is not an adaptor.
Hum, IMHO,yes. It is just adapt a class from the internal Minor function object convention to the external Major function object.
IIRC, Boost.Phoenix also uses "function".
Yes, I saw it too. But Phoenix is not a first class boost library yet :). when it will be reviewed, I'll make the same comment.
We have namespaces so that it should be ok. :-)
I rarely use Boost.Bind and Boost.Lambda in production code.
Why not? I do all the time.
I don't need a hammer to break an egg. :-)
- implicit. "Implicit adds implicit conversion support to a cast from function". What does that means? What are the use cases?
It automatically passes initialized types to cast functions.
could you provide an example?
std::string str = lexical(20); is translated into: std::string str = X_lexical_cast<std::string>()(20); is translated into: std::string str = lexical_cast<std::string>(20); The target type std::string is automagically passed to X_lexical_cast<>. So, you don't need to specify a target type.
I couldn't find boost.bind apply_visitor.
The actual name is visit_each (which I think is the protocol used by apply_visitor). There is some reference in bind/storage.hpp. The actual api is not documented, but I guess that the intent is that boost::visit_each(vistitor, bind-expression); should iterate on all arguments closed in the bind expression. Searching the boost mailing list reveals that bind_visitor has been broken for a while. I do not know if it is still true (I have never used it - yet).
It seems challenging. E.g. Making a function adapting expression into Proto tree expression!
If reviewers regard it as an inadequate component, I will simply remove nestN from Egg. BTW, how can we write nested lambda using phoenix?
lambda[ for_each(_1, lambda(_a = _1)[ front(_a) += _1] )(range)
[at least It should work, given appropriate definitions of for_each and front]
It seems different motivation. nestN returns a function which returns a function which returns a.... e.g. nest3(....)(1)(2,3)(4);
bll_N is a model of LexicallyTypedObject so that you don't need to remember the name "placeholderN_type".
so now I have to remember two types instead of one :)
You have to remember placeholder1_type is const-qualified.
- construct_braced{1,2}. Eh? what is this for?
- construct_variadic. Same as above.
egg::generator needs this to initialize pod types.
Is it a general purpose utility of just an implementation detail?
I want egg::generator to support POD types.
Unless lambda registers its types of course. Anyways, It would be enough for me if this worked:
BOOST_AUTO(foobar, compose(foo, bar));
I will consider Boost.Typeof support. Regards, -- Shunsuke Sogame

AMDG shunsuke wrote:
- "Binding functions"
"boost::result_of isn't used for now". Why?
Because of a bug described in the `egg::result_of_` section.
Ah, now understand why I'm missing some documentation details! the documentation doesn't always clearly show which words are links. for example in my browser result_of_ is not visually distinguished from the rest of the paragraph. I do not know if it is a problem of my browser of you need to fix your CSS.
I'm using CSS of boost. I hope it will be updated.
You can fix the problem by not using code markups inside links. In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
shunsuke wrote:
- "Binding functions"
"boost::result_of isn't used for now". Why?
Because of a bug described in the `egg::result_of_` section.
Ah, now understand why I'm missing some documentation details! the documentation doesn't always clearly show which words are links. for example in my browser result_of_ is not visually distinguished from the rest of the paragraph. I do not know if it is a problem of my browser of you need to fix your CSS.
I'm using CSS of boost. I hope it will be updated.
You can fix the problem by not using code markups inside links.
I didn't know how "code with links" can be visually distinguished. Anyway I should have removed code markups. Regards, -- Shunsuke Sogame

[trimming out everything we agree] On Thu, Apr 10, 2008 at 2:32 AM, shunsuke <pstade.mb@gmail.com> wrote:
Giovanni Piero Deretta wrote:
Btw, can you explain me (again, please :P) why
result_of<T_curry2(F)> >::type const c = {{{}};
isn't enough? I guess I should see static_ implementation.
Because, in general, a higher-order function must support stateful functions. `static_` makes a default-constructed function object on-the-fly and forwards arguments to it. ( I call it "staticalization". ) Thus, `static_` can offer the static-initialization.
Duh! now it is obvious. Thanks again for the expalination.
What about collapsing static_ and result_of in a single class, and allowing arbitrary composition:
apply<compose, apply<compose, my_fun1, my_fun2>, my_fun3>::type c = {{}};
The apply name is already taken by MPL, but maybe something of the sort.
I chose to minimize the set of names.
static_< result_of<compose(result_of<compose(my_fun1, my_fun2)>::type, my_fun3)> >::type const c = {{}};
is enough. Users don't need to remember yet another metafunction `apply`. (result_of expression is a little combersome, though.) If you need static-initialization, wrap a result_of expression by `static_`. Isn't it simple?
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.
Also, it is only the outmost metafunction(i.e. static_) that knows when "staticalization" should be performed. Otherwise, all the metafunction have to perform "staticalization", which is wasteful.
Ok, now that I understood how static_ works, agree 100%.
Also I do not like the T_* convention to name function types. I liked best the old op_* convention.
LexicallyTypedObject concept is not restricted to FunctionObjects. "T_" is short of "typeof". This concept is a workaround for "missig decltype" in C++03.
What about using the prefix 'typeof_' or a postfix '_type'? I really dislike that uppercase T. Maybe even a postfix _t would be more than enough.
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.
Even better would be to segregate function object types to their own namespace, a-la fusion or proto. (i.e. the functional namespace).
See this:
namespace poost { namespace op { struct foo {}; }
op::foo const foo = {};
namespace nested { namespace op { struct bar {}; } op::bar const bar = {};
void test() { op::foo my_foo = foo; // doesn't compile } } }
Thus, I've rejected segregated-namespace-way.
uh? ... void test() { poost::op::foo my_foo = foo; // it compiles! }
Seems a very simple fix (and arguably the right thing in the first place!)
A result_of expression becomes long.
You can always namespace aliases. (I also *always* namespace qualify my function objects, not only their types).
This is a decision from my experince.
I had a different experience, but probably your is more extensive.
Making a function object pipable should just be a matter of deriving it from an (empty) egg::pipable, which would manifest the intention of the object to participate in pipelines.
I'm not sure it has an advantage over higer-order functions.
Less intellectual overhead :). I need to know less things to appreciate what 'pipable' means. Concept should be as simple as possible IMHO. (you can of course add "... but not simpler" :) )
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 meant Egg of course. What I wanted to say is:
Egg provides a templated operator| in egg namespace. There is a single implementation for this operator and is:
namespace pibable_ {
struct pipable {}; // ADL hook
template<typename Lhs, typename Rhs> typename boost::lazy_enable_if<bost::is_base_and_derived<pipable, Rhs>, boost::result_of<Rhs(Lhs&)> >::type operator|(Lhs& lhs, Rhs rhs) { return rhs(lhs); }
template<typename Lhs, typename Rhs> typename boost::lazy_enable_if<bost::is_base_and_derived<pipable, Rhs>, boost::result_of<Rhs(const Lhs&)> >::type operator|(const Lhs& lhs, Rhs rhs) { return rhs(lhs); } }
Any unary function object that wants to model the pipable concept must derive from pipable_::pipable. This will trigger ADL and will find the operator | when necessary. (In c++0x of course you would put operator| in the global namespace and make it a template function constrained on the (non auto) concept Pipable)
I can't always use inheritance -- for stateful static initialization.
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.
Also, how can we make `_1+_2` pipable? A higher-order function is needed, after all.
of course: you write pipable(_1 + _2), to add 'pipability' to non pibable objects on the fly.
This of course only work with unary callable entities. to make a non-unary entity unary, apply the appropriate curry/bind grease :). This will also get rid of the need for Ambi.
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). 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).
As an extension (I'm not proposing it, it is just for the sake of discussion), '|' could be a synonym for compose (IIRC it is spelled '$' in haskell):
A PipableFunctionObject supports '$' using `operator|=`.
I think that, in my scenario, |= would more like the Haskel '.' operator (i.e. compose).
It might be different what you expect, though.
Of course in egg currently | and |= do not have compose like behaviour.
if lhs and rhs are callable entites (in practice you detect pipability): a | b is the same as: compose(b, a);
else if only b is a callable entity: a | b is the same as compose(b, always(a));
else the expression is illegal.
[IIRC in haskel values are in practice treated as nullary functions, so the use of 'always' here would mimic the functional comunity usage]
IMO, this seems to introduce unneeded complexity. "If 'a' is callable,... else if 'b' is pipable,... else if 'c' is a placeholder..." seems a bad switch statement.
you only need to handle pipable: template<typename Lhs, typename Rhs> enable_if_pipable_rhs_and_not_lhs<Rhs, Lhs, result_of<Rhs(Lhs)> >::type operator|(Lhs lsh, Rhs rhs) { return rhs(lhs); } template<typename Lhs, typename Rhs> enable_if_pipable_rhs_and_lhs<Rhs, Lhs, result_of<compose(Rhs, Lhs)> >::type operator|(Lhs lhs, Rhs rhs) { return compose(rhs, lhs); } Apply appropriate magic to handle lvalues and rvalues lhs in the first function. The implementation of enable_if_pipable_rhs_and_[not_]lhs is obvious.
This means that you can create pipelines of transforms:
map(my_range, my_first_view|my_second_view)
Would be the same as:
map(my_range, compose(my_second_view, my_first_view));
I understand it.
or
map(my_range, my_first_view) | protect(lazy(_1, my_second_view))
Sorry, I couldn't understand this expression.
Of course, it is wrong :). It is missing the second 'map': map(my_range, my_first_view) | protect(lazy(map)(_1, my_second_view)) You need protect here, or | would be part of the lambda expression.
Sorry, I couldn't understand this proposal. What does `x | foo(_, 10, "bar")` mean?
hum, let me see, in egg syntax it should be:
compose(lazy(foo)(_1, 10, "bar), always(x))
I understand it.
but see below:
Also, f(_, 10, _)("baz", "bar"); seems supported by egg::lazy.
yes, the only difference is that the result is not a lambda expression (as if there was an implicit protect): see the difference between:
lazy(foo)(lazy(bar)(_1, _2)); // ll::bind(foo, ll::bind(bar, _1))
I understand it.
and:
lazy(foo)(protect(lazy(bar)(_1, _2))); // ll::bind(foo, protect(ll::bind(bar, _1)))
with my syntax (actually this is lifted directly from the generalized currying in FC++), you could spell the latter:
foo(bar(_,_)); // s
I'm lost. How can I use this `foo(bar(_,_))` ?
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.
this is important if egg were (as one would expect) to register its operator| with boost::lambda:
map(my_range, _1 | lazy(is_less)(_1, 10)); // does not work!
map(my_range, _1 | protect(lazy(is_less)(_1, 10))) ; //ok
map(my_range, _1 | is_less(_, 10)); // also ok
I'm lost again. Is `_1 | lazy(is_less)(_1, 10)` translated into `compose(lazy(is_less)(_1, 10), _1)` ?
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)));
A nice name for the generalized curry operation is of course curry:
BTW, strictly speaking, this is not a currying. This is a partial application.
I still can't understand this subtlety :(.
auto is_less = curry(is_less_non_curriable);
assert( is_less(_, 10)(7) == true );
This is trivially implementable with lazy + protect, but an ah-hoc implementation might be simpler and easier on the compiler (no need for full blown lambda support). Also, i spell the missing parameters '_' because that's what FC++ used, 'deferred' might also be a good name.
What do you think?
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 :)
Or better, modify boost.lambda so that any Polymorphic function object work with it (shouldn't be hard), so that we do not need an ad-hoc concept.
It seems hard.
I do not think so, in fact I think that there are patches around. On the other hand, I'm not the one doing it, so I shouldn't complain.
IIRC, Daniel Walker was trying it.
Yes.
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?
I rarely use Boost.Bind and Boost.Lambda in production code.
Why not? I do all the time.
I don't need a hammer to break an egg. :-)
:). I agree that Lambda is quite hammer like, but bind is simple and quite
If reviewers regard it as an inadequate component, I will simply remove nestN from Egg. BTW, how can we write nested lambda using phoenix?
lambda[ for_each(_1, lambda(_a = _1)[ front(_a) += _1] )(range)
[at least It should work, given appropriate definitions of for_each and front]
It seems different motivation. nestN returns a function which returns a function which returns a.... e.g. nest3(....)(1)(2,3)(4);
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.
bll_N is a model of LexicallyTypedObject so that you don't need to remember the name "placeholderN_type".
so now I have to remember two types instead of one :)
You have to remember placeholder1_type is const-qualified.
Ah, that's a significan difference. I didn't catch it from the documentation.
Unless lambda registers its types of course. Anyways, It would be enough for me if this worked:
BOOST_AUTO(foobar, compose(foo, bar));
I will consider Boost.Typeof support.
This is just really low priority though, I do not consider it a must-have. -- gpd

On Thu, Apr 10, 2008 at 3:10 PM, Giovanni Piero Deretta <gpderetta@gmail.com> wrote:
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 ] ];
this should be: auto always = lambda [ lambda(_a = _1)[ _a ] ]; // the inner lambda is nullary, not unary
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.
-- gpd

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

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

Giovanni Piero Deretta wrote:
After all, I will follow Boost.Fusion (and other Boost libraries). Ditto `X_` prefix.
the 'functional' namespace?
I don't know where typenames of function objects will be placed. I will consult Dan Marsden.
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
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. :-(
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.
I will consult Daniel. IIRC, that patch needs some modifications.
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.
Right. It is a defect.
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.
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);
// more fun! auto always_the_sum = lambda[ curry1(lambda[arg1])(arg1 + arg2) ];
auto always_10 = always_the_sum(4, 6);
assert(always_10() == 10);
How about: auto always_the_sum = close1(close2, _1+_2);
(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).
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).
Thanks! -- Shunsuke Sogame

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
participants (3)
-
Giovanni Piero Deretta
-
shunsuke
-
Steven Watanabe