Boost logo

Boost :

Subject: Re: [boost] Boost.Local Review (Nov 10, 2011 to Nov 19, 2011)
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-11-18 04:44:42


On Wed, Nov 16, 2011 at 10:24 AM, Lorenzo Caminiti
<lorcaminiti_at_[hidden]> wrote:
> On Wed, Nov 16, 2011 at 9:34 AM, Andrzej Krzemienski <akrzemi1_at_[hidden]> wrote:
>> How about Boost.Closure library? "Local" may not even be necessary, because
>> "closure" somehow implies locality. (you do not need a global closure,
>> because global function will do).
>
> Yes, I was thinking about it after you suggest it yesterday. I'd say
> the options become:

After studying in details a few references:
http://en.wikipedia.org/wiki/Closure_(computer_science)
http://en.wikipedia.org/wiki/Anonymous_function
http://en.wikipedia.org/wiki/Funarg_problem
N2550, N3242

I concluded that, if there are no objects, I would like to rename my
library Boost.Closure as suggested by Andrzej:

Boost.Closure
BOOST_CLOSURE, BOOST_CLOSURE_END (for local functions with their bound
variables)
BOOST_CLOSURE_SCOPE_EXIT, BOOST_CLOSURE_SCOPE_EXIT_END
BOOST_CLOSURE_BLOCK, BOOST_CLOSURE_BLOCK_END

The reason is because the definition of closure is (from Wikipedia):
"In computer science, a closure (also lexical closure, function
closure or function value) is a function together with a referencing
environment for the non-local variables of that function. A closure
allows a function to access variables outside its typical scope". Such
a definition matches precisely what my library does.

I also realized that I need to fix a bug when the closure is returned
outside its local scope where it is defined. Again from Wikipedia: "A
language implementation cannot easily support full closures if its
run-time memory model allocates all local variables on a linear stack.
In such languages, a function's local variables are deallocated when
the function returns. However, a closure requires that the free
variables it references survive the enclosing function's execution.
Therefore, those variables must be allocated so that they persist
until no longer needed. This explains why, typically, languages that
natively support closures also use garbage collection. The alternative
is for the language to accept that certain use cases will lead to
undefined behaviour, as in the proposal for lambda expressions in
C++." When the closure is returned outside its definition scope, if a
variable is bound by reference, the behaviour is correctly undefined
because the referenced variable does not exist anymoore. However, if
the variable is bound by value, the closure should work even outside
its local scope of definition instead currently my library produces an
undefined behaviour also with value bindings so I have to fix that.
For example:

boost::function<void ()> counter() {
    int x = 0;
    int delta = 2;
    void BOOST_CLOSURE(bind& x, bind delta) {
        x += delta;
        std::cout << "x = " << x << std::endl;
    } BOOST_CLOSURE_END(increment)
    increment(); // ok
    return increment;
}

int main() {
    boost::function<void ()> inc = counter();
    inc(); // (1) error (undefined behaviour)
    return 0;
}

(1) correctly doesn't work because x is bound by reference (and x no
longer exists after counter() returns). However, if x was not bound by
reference (e.g., make it a function parameter) then (1) should work
(but currently it doesn't in my library implementation so I have to
fix that):

boost::function<void (int&)> counter() {
    int delta = 2;
    void BOOST_CLOSURE(int& x, bind delta) {
        x += delta;
        std::cout << "x = " << x << std::endl;
    } BOOST_CLOSURE_END(increment)
    return increment;
}

int main() {
    int x = 1;
    boost::function<void (int&)> inc = counter();
    inc(x); // undefined behaviour now but it should work...
    return 0;
}

AFAIU, C++11 lambdas work the same way (I also run a few C++11 lambda
examples to verify that): If you bind by reference then you can only
use the lambda within the scope in which the reference is valid but if
you bind by value you don't have that constraint.

Thanks.
--Lorenzo


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk