Larry Evans
[...]
The correspondence between the two, IIUC, is the let-expresion:
( let ( [id1 val-expr1] [id2 val-expr2] [id3 val-expr3] ... ) body-expr )
would be, using generic-lambdas:
[] ( auto id1 , auto id2 , auto id3 ) { return body-expr } ( val-expr1 , val-expr2 , val-expr3 ... )
Is that about right?
That would be it, but you could also use the lambda capture. If I remember, my motivation for let expressions was to define branches inline when I had conditionals. Here's what I do in Hana when I want to branch on a (possibly compile-time) condition: auto result = eval_if(condition, [](auto _) { return then_branch; }, [](auto _) { return else_branch; } ); Now, I can use the lambda capture if there's something I need to capture in either branches. I'll explain the dummy argument now. Since we use lambdas, we achieve one level of laziness; we achieve runtime laziness. Only the branch which is chosen by the condition will be executed inside eval_if, so all is good. However, since we also want to support heterogeneous branches, and so branches whose well-formedness might depend on the value of the condition, we use a dummy argument to delay the template instantiation inside the branches. Let's pretend our branches are functions of some arbitrary x: auto result = eval_if(condition, [](auto _) { return then_branch(_(x)); }, [](auto _) { return else_branch(_(x)); } ); Now, because the compiler does not know what is _ until either branch is called, it can't instantiate a (possibly invalid) branch. Then, the trick we play to the compiler is that eval_if always calls us with an identity function, so _(x) is actually x, but not knowing it until the last moment bound the compiler to wait before instantiating the whole expression. This is long, but I hope it clarifies why, IMO, we don't need let expressions anymore. Louis