Template metaprogramming libraries

Hi Boost developers, I am a PhD student at Eotvos Lorand University, Budapest. My research area covers C++ template metaprogramming. As part of my research I have developed four template metaprogram libraries based on Boost.MPL. On my conference appearances I was encouraged to submit my libraries to the Boost sandbox. Here is a short summary of the libraries: metaparse A tool for building embedded DSLs in C++. This is a compile-time parser generator library. Using it one can build parsers that take compile-time strings as input text and parse them as part of the C++ compilation process. One can think of it as using Spirit at compile-time. safe_printf Typesafe printf implementation using metaparse. It provides printf (sprintf, fprintf) functions taking the format string as a template argument and type-checking it at compile-time. It is a practical application of the metaparse library. metamonad Monad implementation for C++ template metaprograms. The library provides a framework for using monads in C++ at compile-time. The library provides an embedded language for C++ template metaprogramming similar to Haskell's do-notation. Using it, template metaprograms can be written with a syntax that resembles procedural code. Unlike the approach presented at this year's Boostcon, my library focuses on monads evaluated completely at compile-time. The library contains implementations for a number of monads available in Haskell (Maybe, Either, Reader, Writer, State, etc.). As an addition, the library contains a monad for error propagation in C ++ template metaprogramming. Based on the similarities of monadic error propagation and exception handling in runtime C++, the library provides an embedded language that resembles to exception handling. Using it, one can throw and catch "exceptions" at compile-time. metatest Unit testing library for C++ template metaprograms. If a metaprogram test case fails, it does not produce compilation error, but makes the result information available at runtime. Using this one can generate advanced reports and integrate the results into unit testing frameworks for runtime C++ code. The library contains code that integrates it with Boost.Test. The source code, unit tests and examples for the library are available at http://github.com/sabel83/mpllibs I've tested the libraries with the following compilers: - gcc 4.5 - clang 2.8 - Visual C++ 10 Full documentation of the libraries can be found at http://abel.web.elte.hu/mpllibs. Publications related to the libraries: http://abel.sinkovics.hu/?mod=kutat I would like to ask you for access to the Boost sandbox and I would appreciate all feedback from the Boost community. Best regards, Abel Sinkovics

Hi Abel, This sounds like interesting work! Exceptions in TMP? Wow. On Sep 7, 2011, at 4:29 PM, Ábel Sinkovics wrote:
metaparse
A tool for building embedded DSLs in C++. This is a compile-time parser generator library. Using it one can build parsers that take compile-time strings as input text and parse them as part of the C++ compilation process. One can think of it as using Spirit at compile-time.
I've also done some compile-time parsing, though not of strings, but of types (specifically, of template expressions). I'd be interested to see if our approaches are similar; I'll take a look. My code is at https://svn.boost.org/svn/boost/sandbox/metagraph/boost/metagraph/angly It basically constructs a DFA and runs it at compile-time If you don't hear back on this thread, you should write to the moderators at boost-owner@ the same domain in order to get sandbox access. Info is here: http://www.boost.org/community/sandbox.html https://svn.boost.org/trac/boost/wiki/BoostSubversion Although, your code doesn't really need to be in the sandbox to get reviewed. Cheers, Gordon

Hi Gordon, My parsing library is based on parser combinators and monads. I need to understand how your code works to see the differences and similarities. Do you have documentation/examples somewhere? Regards, Abel Am Donnerstag, den 08.09.2011, 23:15 -0400 schrieb Gordon Woodhull:
Hi Abel,
This sounds like interesting work! Exceptions in TMP? Wow.
On Sep 7, 2011, at 4:29 PM, Ábel Sinkovics wrote:
metaparse
A tool for building embedded DSLs in C++. This is a compile-time parser generator library. Using it one can build parsers that take compile-time strings as input text and parse them as part of the C++ compilation process. One can think of it as using Spirit at compile-time.
I've also done some compile-time parsing, though not of strings, but of types (specifically, of template expressions). I'd be interested to see if our approaches are similar; I'll take a look.
My code is at https://svn.boost.org/svn/boost/sandbox/metagraph/boost/metagraph/angly It basically constructs a DFA and runs it at compile-time
If you don't hear back on this thread, you should write to the moderators at boost-owner@ the same domain in order to get sandbox access.
Info is here: http://www.boost.org/community/sandbox.html https://svn.boost.org/trac/boost/wiki/BoostSubversion Although, your code doesn't really need to be in the sandbox to get reviewed.
Cheers, Gordon
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Hi Abel, I've taken a quick glance through your docs. It's neat that you support a sort of imperative (or as you say, procedural) interface within your monad EDSL, using set<>. I imagine that will make some metaprograms easier to understand. I also think let<> will help readability. Currently I rely on typedefs within the class body and that is not so pretty or consistent. I guess the difference between your lambda<> and mpl::lambda is that yours works more like in FP languages whereas MPL's transforms placeholder expressions into metafunctions. Is there a summary somewhere of the difference between your approach and MPL's?
My parsing library is based on parser combinators and monads.
Oh, interesting - looks like it is of equivalent power but a higher-level interface, more similar to regular expressions. I like that better and hope to build in that direction.
I need to understand how your code works to see the differences and similarities. Do you have documentation/examples somewhere?
I haven't yet documented Angly. There is my blog metagraph.info and the best example is metagraph/libs/metagraph/example/angly_graph_parser.cpp From that, a simple example of the sorts of expressions I'm trying to parse: typedef graph<node<A, edge<t, B>, edge<u, C> >, node<B, edge<v, D> >, node<C, edge<w, E> >, node<D, edge<x, F> >, node<E, edge<y, F>, edge<z, G> > > adjacencies; I.e. declarative EDSLs within the "angly" template expression syntax. I also considered imperative EDSLs but that's not at all where I'm going with this: I'm just trying to get a nice language for declaring metadata. Cheers, Gordon

On Sep 9, 2011, at 5:12 PM, Gordon Woodhull wrote:
Is there a summary somewhere of the difference between your approach and MPL's?
Okay I have read Functional Extensions to the Boost Metaprogram Library Now I get it, lazy extensions for MPL, and all the other goodies you would expect from a haskell-like functional programming library. And now monads too. Bravo! I hope you bring these libraries to Boost. I crave the simpler syntax and ability to create more complex of pure lazy evaluation. Have you measured compilation performance versus more-eager MPL implementations of the same algorithms, to see how bad the abstraction penalty is? I am looking at porting various Boost.Graph algorithms to my proposed MPL.Graph. Do I understand that monads will help me define metadata structures like heaps and forests that don't seem to "map" easily to functional programming? Cheers, Gordon

Hi Gordon, "Nested Lambda Expressions with Let Expressions in C++ Template Metaprograms" explains metamonad's lambda expressions. The major difference between that approach and MPL's lambda expressions is that metamonad lambda expressions let the user specify the name of the arguments instead of calling them _1, _2, etc. Using these lambda expressions I could embed lambda expressions inside other lambda expressions. The implementation of do-syntax relies on these lambda expressions as well. I'm not aware of techniques based on monads that help implementing data-structues. They are good at abstracting behaviours (error handling, non-determinism, etc.), they should help you with error propagation in your algorithms (see compile-time exceptions in metamonad). I've done a measurement: I've called "lazy_eval_if" / "eval_if + eager condition evaluation" 1000 times (1.6GHz Atom processors, 1 GB memory, Linux, GCC 4.5.2) and measured the compilation speed with "time". Here are the results: lazy_eval_if: 3.89 s eval_if: 3.65 s As you can see, there is some overhead (lazy_eval_if uses eval_if), however it may be different with other compilers. Regards, Abel Am Freitag, den 09.09.2011, 20:05 -0400 schrieb Gordon Woodhull:
On Sep 9, 2011, at 5:12 PM, Gordon Woodhull wrote:
Okay I have read
Functional Extensions to the Boost Metaprogram Library
Now I get it, lazy extensions for MPL, and all the other goodies you would expect from a haskell-like functional programming library.
And now monads too.
Bravo! I hope you bring these libraries to Boost. I crave the simpler syntax and ability to create more complex of pure lazy evaluation.
Have you measured compilation performance versus more-eager MPL implementations of the same algorithms, to see how bad the abstraction penalty is?
I am looking at porting various Boost.Graph algorithms to my proposed MPL.Graph. Do I understand that monads will help me define metadata structures like heaps and forests that don't seem to "map" easily to functional programming?
Cheers, Gordon
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 09/10/11 06:03, Ábel Sinkovics wrote:
Hi Gordon,
"Nested Lambda Expressions with Let Expressions in C++ Template Metaprograms" explains metamonad's lambda expressions. The major difference between that approach and MPL's lambda expressions is that metamonad lambda expressions let the user specify the name of the arguments instead of calling them _1, _2, etc. Using these lambda expressions I could embed lambda expressions inside other lambda expressions. The implementation of do-syntax relies on these lambda expressions as well.
Hi Abel, Are you saying that using the existing mpl, one cannot embed lambda expressions inside other lambda expressions? Is that mpl problem an example of name capture: http://dictionary.reference.com/browse/name+capture ? -regards, Larry

Hi Larry,
Are you saying that using the existing mpl, one cannot embed lambda expressions inside other lambda expressions? Is that mpl problem an example of name capture:
http://dictionary.reference.com/browse/name+capture
?
You can embed MPL lambda expressions inside other ones. I couldn't find a way of accessing the arguments of the outer lambda expression from the inner one, because the names _1, _2, etc were referring to the arguments of the inner expression, not the outer one (they were shadowing the outer ones). I'd express it with "\x.\x.x" in lambda calculus. Inside the inner lambda abstraction "x" refers to the argument of the inner, not the outer one. Regards, Abel

On Sun, Sep 11, 2011 at 12:01 AM, Ábel Sinkovics <abel@elte.hu> wrote:
Hi Larry,
Are you saying that using the existing mpl, one cannot embed lambda expressions inside other lambda expressions? Is that mpl problem an example of name capture:
http://dictionary.reference.com/browse/name+capture
?
You can embed MPL lambda expressions inside other ones. I couldn't find a way of accessing the arguments of the outer lambda expression from the inner one, because the names _1, _2, etc were referring to the arguments of the inner expression, not the outer one (they were shadowing the outer ones).
I'd express it with "\x.\x.x" in lambda calculus. Inside the inner lambda abstraction "x" refers to the argument of the inner, not the outer one.
A while ago someone suggested (on the developers' list) adding de Bruijn indices [1] to Boost.Bind and/or Boost.MPL (and may have provided at least a sample implementation for one or the other, I'm not sure), which ( I think) would allow you to do what you want to do. There might be some protect and bind combination of contortions to do what you want, but I'd certainly agree that, even if it could be done, it probably wouldn't be pretty. [1] http://en.wikipedia.org/wiki/De_Bruijn_indices - Jeff

On 09/11/11 02:30, Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Sep 11, 2011 at 12:01 AM, Ábel Sinkovics <abel@elte.hu> wrote:
Hi Larry,
Are you saying that using the existing mpl, one cannot embed lambda expressions inside other lambda expressions? Is that mpl problem an example of name capture:
http://dictionary.reference.com/browse/name+capture
?
You can embed MPL lambda expressions inside other ones. I couldn't find a way of accessing the arguments of the outer lambda expression from the inner one, because the names _1, _2, etc were referring to the arguments of the inner expression, not the outer one (they were shadowing the outer ones).
I'd express it with "\x.\x.x" in lambda calculus. Inside the inner lambda abstraction "x" refers to the argument of the inner, not the outer one.
A while ago someone suggested (on the developers' list) adding de Bruijn indices [1] to Boost.Bind and/or Boost.MPL (and may have provided at least a sample implementation for one or the other, I'm not sure),
I attempted an implementation, but was not successful, as indicated in this post: http://lists.boost.org/Archives/boost/2010/09/171123.php
which ( I think) would allow you to do what you want to do.
There might be some protect and bind combination of contortions to do what you want, but I'd certainly agree that, even if it could be done, it probably wouldn't be pretty.
I remember doing something with those templates to workaround a problem that *seemed* like it was a name capture problem; so, I'd agree with Jeffrey here that it might work with some combination of bind protect (I also think I used lambda).
[1] http://en.wikipedia.org/wiki/De_Bruijn_indices
- Jeff
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Tue, Sep 13, 2011 at 1:44 PM, Dave Abrahams <dave@boostpro.com> wrote:
A while ago someone suggested (on the developers' list) adding de Bruijn indices [1] to Boost.Bind and/or Boost.MPL (and may have provided at least a sample implementation for one or the other, I'm not sure), which ( I think) would allow you to do what you want to do.
That was David Sankel, IIRC.
Thus invoked... On Sun, Sep 11, 2011 at 9:22 AM, Larry Evans <cppljevans@suddenlink.net>wrote:
On 09/11/11 02:30, Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Sep 11, 2011 at 12:01 AM, Ábel Sinkovics <abel@elte.hu> wrote:
Hi Larry,
Are you saying that using the existing mpl, one cannot embed lambda expressions inside other lambda expressions? Is that mpl problem an example of name capture:
http://dictionary.reference.com/browse/name+capture
?
You can embed MPL lambda expressions inside other ones. I couldn't find a way of accessing the arguments of the outer lambda expression from the inner one, because the names _1, _2, etc were referring to the arguments of the inner expression, not the outer one (they were shadowing the outer ones).
I'd express it with "\x.\x.x" in lambda calculus. Inside the inner lambda abstraction "x" refers to the argument of the inner, not the outer one.
A while ago someone suggested (on the developers' list) adding de Bruijn indices [1] to Boost.Bind and/or Boost.MPL (and may have provided at least a sample implementation for one or the other, I'm not sure),
I attempted an implementation, but was not successful, as indicated in this post:
http://lists.boost.org/Archives/boost/2010/09/171123.php
which ( I think) would allow you to do what you want to do.
There might be some protect and bind combination of contortions to do what you want, but I'd certainly agree that, even if it could be done, it probably wouldn't be pretty.
I remember doing something with those templates to workaround a problem that *seemed* like it was a name capture problem; so, I'd agree with Jeffrey here that it might work with some combination of bind protect (I also think I used lambda).
I'm the one who designed the DeBruijn bind syntax and implementation that Dave A and Larry referenced. The DeBruijn bind syntax would work for compile time or run time. The sample implementation was for run time. DeBruijn bind syntax can represent strictly *more* functions than the traditional bind syntax, even with protect. Furthermore, the functions that DeBruijn bind can define, that traditional bind cannot, are useful and interesting. An example is the flip function: haskell syntax: flip :: ((a,b) -> c) -> ((b,a) -> c) flip f (x,y) = f (y,x) intuition: flip is a function that takes in a two-argument function and returns a two-argument function that is essentially the same, but the arguments are reversed. lambda syntax: λf.λ(a,b). f (b,a) De Bruijn syntax (any lambda expression can be transformed into this syntax): λ₁λ₂2₁(1₂, 1₁) De Bruijn Bind syntax (any De Bruijn syntax can be transformed into this syntax): lam<1>( lam<2>( app( _2_1, _1_2, _1_1 ) ) ) Now lets see why flip can never be defined with traditional bind syntax. First, we give a meaning to traditional bind expressions in order to understand what we're talking about. Consider boost::function<blah> = bind(_1, bind( _2, protect( bind( _2, _1 )))). For that top level bind expression, wrap it in a protect. This doesn't change the meaning and will aid our translation. boost::function<blah> = protect( ... ). Each protect has a given size. This size is defined as the largest _x that is underneath it, but not underneath another sub-protect. Annotate each protect with its size. protect[2]( bind(_1, bind( _2, protect[3]( bind( _3, _1 ))))). Now, for each protect, generate a list of "size" globally unique identifiers and replace every _x underneath (that isn't within a sub-protect) with the appropriate identifier. In this example, first we do this to the outer protect: protect[2,x,y]( bind(x, bind( y, protect[3]( bind( _3, _1 ))))). And then the inner protect protect[2,x,y]( bind(x, bind( y, protect[3,z,a,b]( bind( z, a ))))). Now rename protect to λ and bind(a,b,c...) to a(b,c...) λ(x,y). x( y( λ(z,a,b). z(a))) What we have here is a translation from any bind expression into its corresponding lambda expression (extended with multiple arguments in the expected way). Given this meaning, it is easy to see that a given lambda (introduced by protect), can never reference any arguments but its own. Another limitation is that a given lambda (introduced by protect) must always return the application of some function (so things like λx.44 can't be defined). <rant> Unfortunately traditional bind syntax and it's inherent design flaws has been replicated in several other libraries like mpl, lambda, phoenix, and C++-0x (arg!). It should be noted though that phoenix users can get around this somewhat by using _identifier syntax. </rant> My implementation adds some more goodies (like recursive functions, and TCO), but the main benefit is it fills in the holes of traditional bind and is easier to understand (by understand I mean having a grasp on the underlying meaning of the expressions). David -- David Sankel Sankel Software www.sankelsoftware.com 585 617 4748 (Office)

On Thursday, September 15, 2011 12:31:50 PM David Sankel wrote: <snip>
I'm the one who designed the DeBruijn bind syntax and implementation that Dave A and Larry referenced. The DeBruijn bind syntax would work for compile time or run time. The sample implementation was for run time.
DeBruijn bind syntax can represent strictly *more* functions than the traditional bind syntax, even with protect. Furthermore, the functions that DeBruijn bind can define, that traditional bind cannot, are useful and interesting.
An example is the flip function:
haskell syntax:
flip :: ((a,b) -> c) -> ((b,a) -> c) flip f (x,y) = f (y,x)
intuition:
flip is a function that takes in a two-argument function and returns a two-argument function that is essentially the same, but the arguments are reversed.
<snip>
<rant> Unfortunately traditional bind syntax and it's inherent design flaws has been replicated in several other libraries like mpl, lambda, phoenix, and C++-0x (arg!). It should be noted though that phoenix users can get around this somewhat by using _identifier syntax. </rant>
#include <boost/phoenix.hpp> #include <iostream> namespace phx = boost::phoenix; int main() { using phx::placeholders::_1; using phx::placeholders::_2; using phx::local_names::_a; using phx::local_names::_b; using phx::val; using phx::lambda; auto f = std::cout << _1 << _2 << "\n"; auto flip = lambda(_a = _1)[bind(_a, _2, _1)]; auto flipped_f = flip(f); flipped_f("David.", "Thanks for your unqualified rant, "); } Output: Thanks for your unqualified rant, David.

On Fri, Sep 16, 2011 at 4:51 AM, Thomas Heller <thom.heller@googlemail.com>wrote:
On Thursday, September 15, 2011 12:31:50 PM David Sankel wrote:
<snip>
<rant>
<snip>
It should be noted though that phoenix users can get around
this somewhat by using _identifier syntax. </rant>
#include <boost/phoenix.hpp>
<snip> auto flip = lambda(_a = _1)[bind(_a, _2, _1)];
<snip>
Thanks for your unqualified rant, David.
huh? -- David Sankel Sankel Software www.sankelsoftware.com 585 617 4748 (Office)

On Friday, September 16, 2011 06:17:00 AM David Sankel wrote:
On Fri, Sep 16, 2011 at 4:51 AM, Thomas Heller
<thom.heller@googlemail.com>wrote:
On Thursday, September 15, 2011 12:31:50 PM David Sankel wrote: <snip>
<rant>
<snip>
It should be noted though that phoenix users can get around
this somewhat by using _identifier syntax. </rant>
#include <boost/phoenix.hpp>
<snip>
auto flip = lambda(_a = _1)[bind(_a, _2, _1)];
<snip>
Thanks for your unqualified rant, David.
huh?
Is this not what you were saying wasn't possible with phoenix? Having a De Brujin style syntax is perfectly possible in phoenix. It just hasn't been done yet cause, as you saw in my example, can be expressed by using phoenix local variables.

On Fri, Sep 16, 2011 at 6:30 AM, Thomas Heller <thom.heller@googlemail.com>wrote:
On Friday, September 16, 2011 06:17:00 AM David Sankel wrote:
On Fri, Sep 16, 2011 at 4:51 AM, Thomas Heller
<thom.heller@googlemail.com>wrote:
On Thursday, September 15, 2011 12:31:50 PM David Sankel wrote: <snip>
<rant>
<snip>
It should be noted though that phoenix users can get around
this somewhat by using _identifier syntax. </rant>
#include <boost/phoenix.hpp>
<snip>
auto flip = lambda(_a = _1)[bind(_a, _2, _1)];
<snip>
Thanks for your unqualified rant, David.
huh?
Is this not what you were saying wasn't possible with phoenix? Having a De Brujin style syntax is perfectly possible in phoenix. It just hasn't been done yet cause, as you saw in my example, can be expressed by using phoenix local variables.
Oh, my bad. When I said "_identifier syntax", I was referring to phoenix local variables. I should have double-checked my phoenix vocab before I wrote. Phoenix locals definitely help fill the coverage problem I referred to. I don't know for sure, but I'd expect phoenix to cover all functions that can be defined in lambda calculus. 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. Don't get me wrong, I think phoenix is an impressive feat. I'm just advocating that we stop perpetuating the troubles caused by basing new libraries on the traditional bind syntax. David -- David Sankel Sankel Software www.sankelsoftware.com 585 617 4748 (Office)

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 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. HTH, -- gpd

On 9/17/2011 2:07 AM, Giovanni Piero Deretta 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 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. 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. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

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)

On Mon, Sep 19, 2011 at 10:23 AM, David Sankel <camior@gmail.com> wrote:
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 );
oops, that should be return boost::phoenix::lambda[ a ]; }
}; }
David
-- David Sankel Sankel Software www.sankelsoftware.com 585 617 4748 (Office)
-- David Sankel Sankel Software www.sankelsoftware.com 585 617 4748 (Office)

on Sun Sep 11 2011, "Jeffrey Lee Hellrung, Jr." <jeffrey.hellrung-AT-gmail.com> wrote:
On Sun, Sep 11, 2011 at 12:01 AM, Ábel Sinkovics <abel@elte.hu> wrote:
I'd express it with "\x.\x.x" in lambda calculus. Inside the inner lambda abstraction "x" refers to the argument of the inner, not the outer one.
A while ago someone suggested (on the developers' list) adding de Bruijn indices [1] to Boost.Bind and/or Boost.MPL (and may have provided at least a sample implementation for one or the other, I'm not sure), which ( I think) would allow you to do what you want to do.
That was David Sankel, IIRC. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 09/13/11 12:44, Dave Abrahams wrote:
on Sun Sep 11 2011, "Jeffrey Lee Hellrung, Jr." <jeffrey.hellrung-AT-gmail.com> wrote:
On Sun, Sep 11, 2011 at 12:01 AM, Ábel Sinkovics <abel@elte.hu> wrote:
I'd express it with "\x.\x.x" in lambda calculus. Inside the inner lambda abstraction "x" refers to the argument of the inner, not the outer one.
A while ago someone suggested (on the developers' list) adding de Bruijn indices [1] to Boost.Bind and/or Boost.MPL (and may have provided at least a sample implementation for one or the other, I'm not sure), which ( I think) would allow you to do what you want to do.
That was David Sankel, IIRC.
Yes: http://lists.boost.org/Archives/boost/2010/09/170487.php

On Sep 10, 2011, at 7:03 AM, Ábel Sinkovics <abel@elte.hu> wrote:
Hi Gordon,
"Nested Lambda Expressions with Let Expressions in C++ Template Metaprograms" explains metamonad's lambda expressions. The major difference between that approach and MPL's lambda expressions is that metamonad lambda expressions let the user specify the name of the arguments instead of calling them _1, _2, etc.
Wonderful! This would clarify my algos greatly. Seems like it shouldn't be much slower either.
I'm not aware of techniques based on monads that help implementing data-structues. They are good at abstracting behaviours (error handling, non-determinism, etc.), they should help you with error propagation in your algorithms (see compile-time exceptions in metamonad).
Hmm, I've got plenty to learn about FP. Monad seems to mean a lot of things. Maybe I was only thinking of the kind that wraps real side effects like memory writes. Anyway this still seems very helpful. In particular I have been writing the tests without failure cases because a compilation error is not a great expected failure. I look forward to exploring further.
lazy_eval_if: 3.89 s eval_if: 3.65 s
As you can see, there is some overhead (lazy_eval_if uses eval_if), however it may be different with other compilers.
Not too bad. I'd like to know what the penalty for a larger algorithm is - also for the lambdas and exceptions/monad stuff. When I get a chance I may try porting my depth_first_search to your libs to find out. Thanks, Gordon

On Fri, 9 Sep 2011, Gordon Woodhull wrote: (snip)
I am looking at porting various Boost.Graph algorithms to my proposed MPL.Graph. Do I understand that monads will help me define metadata structures like heaps and forests that don't seem to "map" easily to functional programming?
Slightly off-topic, but related: another approach to that problem is to use purely functional data structures. There is a book on the topic (http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/05216635...), as well as a thesis available online (http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf). There is a Haskell library, Edison (http://www.haskell.org/ghc/docs/edison/), implementing them, and there is a Functional Graph Library (http://web.engr.oregonstate.edu/~erwig/fgl/) as well. Those might be useful to avoid monads for some of the graph algorithms you want to implement. -- Jeremiah Willcock

On Sep 10, 2011, at 1:31 PM, Jeremiah Willcock <jewillco@osl.iu.edu> wrote:
On Fri, 9 Sep 2011, Gordon Woodhull wrote:
(snip)
I am looking at porting various Boost.Graph algorithms to my proposed MPL.Graph. Do I understand that monads will help me define metadata structures like heaps and forests that don't seem to "map" easily to functional programming?
Slightly off-topic, but related: another approach to that problem is to use purely functional data structures.
Thanks for the references, Jeremiah! Cheers, Gordon

metatest
Unit testing library for C++ template metaprograms. If a metaprogram test case fails, it does not produce compilation error, but makes the result information available at runtime.
I am extremely interested in this capability. The inability to produce failing test cases for metaprograms, is a severe limitation in my opinion. Ben Robinson, Ph.D.

Le 07/09/11 22:29, Ábel Sinkovics a écrit :
Hi Boost developers,
Here is a short summary of the libraries:
metaparse safe_printf metamonad metatest Hi,
Unit testing library for C++ template metaprograms. If a metaprogram test case fails, it does not produce compilation error, but makes the result information available at runtime. Using this one can generate advanced reports and integrate the results into unit testing frameworks for runtime C++ code. The library contains code that integrates it with Boost.Test. A meta program test case fails if you call static assert on some static condition, isn't it. If the user uses Boost.Test or any other kind of runtime check then the compilation doesn't fails. I'm wondering what
I find in general all your libraries quite interesting. What are the dependencies between these sub-libraries? metatest adds to Boost.Test then?
I would like to ask you for access to the Boost sandbox and I would appreciate all feedback from the Boost community.
I hope to comeback with more comments of your libraries soon. Good work, Vicente

Hi Vicente, The sub-libraries have the following dependencies: - metatest doesn't really depend on any of the libraries (one of its examples depends on metamonad, but it can be moved to metamonad) - metamonad depends on metatest - metaparse depends on metatest and metamonad - safe_printf depends on metaparse (it has no test cases yet) Test cases should be nullary metafunctions returning boolean values indicating success/failure of the test case - the condition of the static assertion - instead of using static assertions themselves. Metatest collects this information and displays it in a final summary. A static assertion failure in metatest is similar to a core dump while running runtime tests, the testing library can't catch it. When metafunctions verify their arguments, they can throw compile-time exceptions (implemented in metamonad) instead of using static assertions. Those exceptions can be caught and handled by the testing framework (and added to the test report). Metatest contains a solution for pretty-printing template expressions, thus the reason of failures can be displayed in a standard format independent of the compiler/platform. You can find a number of MPL test cases ported to metatest in the metatest examples (libs/metatest/example/boost_mpl_unit_test in the source tree). You can take a look at them and generate example reports (plain-text, HTML/JavaScript, Boost.Test). Regards, Abel Am Freitag, den 09.09.2011, 21:44 +0200 schrieb Vicente J. Botet Escriba:
Le 07/09/11 22:29, Ábel Sinkovics a écrit : Hi,
I find in general all your libraries quite interesting.
What are the dependencies between these sub-libraries?
A meta program test case fails if you call static assert on some static condition, isn't it. If the user uses Boost.Test or any other kind of runtime check then the compilation doesn't fails. I'm wondering what metatest adds to Boost.Test then?
I hope to comeback with more comments of your libraries soon.
Good work, Vicente
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

We don't use to top post in this ML. Please don't it if you can :) Le 10/09/11 13:05, Ábel Sinkovics a écrit :
Hi Vicente,
The sub-libraries have the following dependencies: - metatest doesn't really depend on any of the libraries (one of its examples depends on metamonad, but it can be moved to metamonad) - metamonad depends on metatest - metaparse depends on metatest and metamonad - safe_printf depends on metaparse (it has no test cases yet) I guess that the dependency to metatest is only for test purposes.
Best, Vicente

Ábel Sinkovics <abel@elte.hu> writes:
metaparse
A tool for building embedded DSLs in C++. This is a compile-time parser generator library. Using it one can build parsers that take compile-time strings as input text and parse them as part of the C++ compilation process. One can think of it as using Spirit at compile-time.
How much overlap does this sub-project have with Boost.Proto? -- John Wiegley BoostPro Computing, Inc. http://www.boostpro.com

On Sep 9, 2011, at 7:46 PM, John Wiegley wrote:
Ábel Sinkovics <abel@elte.hu> writes:
metaparse
A tool for building embedded DSLs in C++. This is a compile-time parser generator library. Using it one can build parsers that take compile-time strings as input text and parse them as part of the C++ compilation process. One can think of it as using Spirit at compile-time.
How much overlap does this sub-project have with Boost.Proto?
It processes mpl::strings not operator expressions. Cheers, Gordon
participants (13)
-
Ben Robinson
-
Dave Abrahams
-
David Sankel
-
Giovanni Piero Deretta
-
Gordon Woodhull
-
Jeffrey Lee Hellrung, Jr.
-
Jeremiah Willcock
-
Joel de Guzman
-
John Wiegley
-
Larry Evans
-
Thomas Heller
-
Vicente J. Botet Escriba
-
Ábel Sinkovics