
On Sun, Nov 20, 2011 at 8:36 PM, Thomas Heller <thom.heller@googlemail.com> wrote:
Please let me clarify my vote again. Please also note, that the quality of the implementation and documentation is out of doubt.
I vote to not include Boost.Local into Boost for the following reason. I obviously can not appreciate the value of local functions in C++. C++, IMHO, has better ways to structure code (namespaces and classes). Therefor, Boost.Local is not an alternative to C++-Lambdas, Boost.Bind, Boost.Lambda or Boost.Phoenix,
That is true for a very simple reason: Boost.Local functions cannot be defined with an expression. Boost.Local don't define lambdas but they define closures at local scope.
but to regular C++ functions That being said, I don't see Boost.Local as a complement to the other already existing functional programming style libraries. I see it as a complement to regular functions. It is true that this implementation of local functions leads to function objects that can be used as callbacks where something callable is expected. However, that does not mean that they are higher order functions, which in turn means that they are not easily composable (that means, there is no way to compose two local functions to form another local function other than calling the macros again). Which has
You can bind a local function to another local function thus composing them together without needing to call the macros again: https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca... int x = 10; int BOOST_LOCAL_FUNCTION(int y, const bind x) { return x + y; } BOOST_LOCAL_FUNCTION(g) int BOOST_LOCAL_FUNCTION(int y, const bind g) { return g(y); } BOOST_LOCAL_FUNCTION_END(f) f(5); This composition is "easy" (if by "easy" we mean "without calling the macros again").
another side effect that they are completely incompatible with the existing solutions (ok, you can bind them again).
Yes, you can compose them by "binding them again" as shown by the example above.
Also, i think the verbosity of the macros defeat their initial purpose of "avoiding cluttering other parts of the program with functions, variables, etc unrelated to those parts". Additionally I can not see how local functions hide any information at all, the information is still visible
Local functions hide information in same sense as explained by N2511. Mainly: 1) Local functions are declared locally, next to the code where they are directly needed (the std::for_each call, etc). 2) Local functions are only visible by the scope that needs to call them (another part of the program can't call them by "mistake" because they are not accessible outside the enclosing function). If you open up the source file, you can of course read the local function code as you can read any other implementation code. However, both local function and implementation code is hidden because it is not accessible from outer scopes within your program.
(although hidden behind two enclosing, quite verbose, macro calls).
Nope, local functions are /not/ hidden by the wrapping macros at all (they are declared by the wrapping macros). They are instead hidden by the enclosing function scope which makes local functions not accessible/visible from outside the enclosing function (even if they are still readable as any non-obfuscated code is). Does this make sense?
I admit the fact, that we as C++ Programmers need Macros to avoid repeating ourselves (aka boilerplate code). A lot of libraries do exactly this, and it is considered good practice. My main point of critique was that the Boost.Local seem to implement a quite complex logic and, basically, their own language. I would not consider the preprocessor the proper place to implement a DSEL.
On the contrary, there's no way to use macros at all without introducing a DSEL by definition. Oops, this might be a controversial point (and I don't want to speak for Paul) but it has been argued that the moment you use a macro you are introducing a DSEL by #definition ;) That is because the pp is a code generator and it has nothing to do with the underling language (C or C++) by definition. Even in simple "function-like" (whatever that means) usage of macros: #define M(x, y) (x-y) // (1) You are introducing a DSEL because the following: M( , 2) // expands to -2 Would not be legal if M was a C++ function but it is legal given that M is a macro! That shows that even the super-simple (1) defines a DSEL with respect to the underlining C++ language. All of that said, I definitively think that you can draw different degrees of complexity of the DSEL you /have to/ define with your macros. You can say that the DSEL introduced by (1) is trivial and acceptable but the DSEL introduced by Boost.Local is too complex and not acceptable (which I think it is your point) [we'll leave out the DSEL introduced by Boost.Contract because on this scale it would be pure madness :) ]. However, they all are DSEL (and not C++) by definition simply because they use macros.
Again, Lorenzo's effort and ingenuity of creating this very library is out of question,
Thanks :)
I solely believe that it is not the proper solution to this problem.
--Lorenzo