
On Fri, Sep 16, 2011 at 11:37 PM, Joel de Guzman <joel@boost-consulting.com>wrote:
On Fri, Sep 16, 2011 at 6:09 PM, David Sankel <camior@gmail.com> wrote:
[...] The reason I said that phoenix "somewhat" gets around the bind heritage problems, which was obscure I admit, was because phoenix's use of traditional bind syntax still leaves a semantic hole.
If someone writes the following:
template< typename F > auto doSomething( F f ) -> decltype(...) { return bind( f, 15, _1) }
And then I call doSomething elsewhere like this,
doSomething( bind( g, 12, _1, _2 ) )
, then the result is something most likely unexpected for the user who knows what doSomething means (it returns a version of f that has 15 filled in as its first argument (λx. λy. x(15,y))), but hasn't read its implementation.
Boost.Lambda has unlambda, which is documented to prevent exactly this
On 9/17/2011 2:07 AM, Giovanni Piero Deretta wrote: problem:
http://www.boost.org/doc/libs/1_47_0/doc/html/lambda/le_in_details.html#lamb...
With a quick search I couldn't find the phoenix equivalent of unlambda, but I'm sure there must be.
Phoenix does not need it because it has explicit 'lambda' (pun unintentional) which is required for passing in higher-order functions (e.g. to phoenix::for_each). IMO, unlambda is a hack around BLL limitations.
This should be the answer David Sankel's concern too (above). I think there's lack of understanding of Phoenix here.
I think you hit the nail on the head with regards to at least my own lack of understanding of Phoenix. Sorry to muddy the waters. I'm excited about getting a better understanding. It looks as if boost.lambda requires the writer of a higher order function to guard its arguments, using unlambda. boost.phoenix, on the other hand, requires the callers of higher order functions to guard its arguments using lambda. Is this correct? For comparison, the boost.lambda example, for_each(a.begin(), a.end(), std::cout << _1 << ' '); Would be the following in boost.phoenix? // assuming _1 is never a function type for_each(a.begin(), a.end(), lambda[ std::cout << _1 << ' ' ]); I didn't catch "explicit lambda required for higher order function calls" from reading the documentation. I wonder how it could fit in the introduction without overly confusing the reader. It seems like a critical thing to know IMO. At any rate, for the record: I am for supporting De Brujin style
in Phoenix. The infrastructure is in place. I see no reason why we can't support both.
That would be great and would be enough to entice me to use phoenix as I love the simplicity of the De Bruijn sytax. Maybe something like following would get a dbb implementation on top of phoenix (extended with DeBruijn indices) namespace dbb { auto _1_1 = boost::phoenix::_1_1; //... auto app = boost::phoenix::bind; struct lam { template< typename A> auto operator()( A a ) -> decltype( ... ) { return boost::phoenix::lambda( a ); } }; } David -- David Sankel Sankel Software www.sankelsoftware.com 585 617 4748 (Office)