Boost logo

Boost :

Subject: Re: [boost] [local_function] any interest in a LocalFunction library?
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2010-09-13 22:52:20


On Mon, Sep 13, 2010 at 5:33 PM, Pierre Morcello
<pmorcell-cppfrance_at_[hidden]> wrote:
>>><lorcaminiti_at_[hidden]> wrote:
>>>
>>> Hello all,
>>>
>>> Local functions are essentially implemented as member functions of
>>> local classes. These member functions do not have to be static and
>>> they could be virtual allowing for a local function to override one
>>> another.
>>>
>>> However, I cannot understand if this overriding "feature" has any
>>> value at all... Have you ever used anything similar? Can you think of
>>> a use case for it?
>
> I can't think of any.
>
>>> this or this_ ?
>
> I personnaly prefer this_ since it is a minor problem, and seems safer.
>
>>> bound or bind?
>
> I am ok with bound, or bind as long as there is no compatibility problems with boost::bind. It would be necessary to explain in the documentation that it is not the 'bind' of boost bind. 'closure' feels a bit long, while 'ref' would even sound better to my humble ears... but this is nothing fundamental to me neither.

Using `(bind)` has not issues with respect to `boost::bind`. That is
because `(bind)` (or any other pp-keyword we end up selecting) has a
meaning only for the preprocessor when the macro is expanded (so there
is absolutely not relationship with `boost::bind`).

>>> Lorenzo wrote :
>>> This functionality plus the one of Boost.Breakable-like
>>> breakability would be provided by Boost.Block in terms of both const
>>> and non-const blocks.
>>> I implemented Boost.Block using Boost.LocalFunction. Note that from
>>> within a Boost.Block, return jumps to the end of the block (and it
>>> does not exit the enclosing function) therefore also proving the
>>> Boost.Breakable functionality discussed in
>>> http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html.
>>> However, I am not sure if this "block breakability" via return is a
>>> feature or a limitation because users could expect `return;` to quit
>>> exit the enclosing function as usual and not just the local
>>> void-function used to implement the Boost.Block
>
> I am myself not convinced by your propositions on this point. If you present it like a 'block', when it's a local fuction directly called, then its more confusing than necessary.
>
> Concerning boost.breakable it was a very simple one liner, which happens to be useful in some cases.
>
> Concerning my earlier suggestion to add to your library was simply a local function called in-place (so presented as a local function). Of course, if you name it 'block' it is confusing. But if you use the term 'function' then it is ok for everyone to use 'return' and have a much easier interface.
>
> instead of :
>
> CONTRACT_DETAIL_BLOCK( (this)(x) )
> {
> if (x <= 0) CONTRACT_DETAIL_BLOCK_BREAK; // `return` jumps to block's end.
> this_->x_ = x; // OK, `f` (so `this`) is non-const member function.
> } CONTRACT_DETAIL_BLOCK_END
>
> using something like :
>
> UNNAMED_FUNCTION( (this)(x) )
> {
> if (x <= 0) return;
> this_->x_ = x; // OK, `f` (so `this`) is non-const member function.
> } UNNAMED_FUNCTION_END
>
> would be clearer in my humble opinion. You could replace UNNAMED_FUNCTION by DIRECT_FUNCTION or something else which clearly shows that it is a function. By the way, this was the interface used by the implementation I send you at the beginning (NESTED_FUNCTION + return) .

I agree, if the macro is named `..._FUNCTION` then `return` is not
confusing. What is the use case for unnamed local functions? Is it
just the breakable feature?

Note that unnamed lambda are more useful because they can be defined
at expression level. If an expression needs a functor, like
`std::for_each()` call, then you defined it using lambda right where
the functor is expected so you do not even need to name the lambda
function -- but that use case does not apply to local functions that
cannot be defined at the expression level. In order to use local
function you have to name them and call them or pass them as functors
to some other function...

All in all, you can always just define a named local function and call
if right away with one extra line of code:

BOOST_LOCAL_FUNCTION(
(void) (unamed)( (bound)((this)(&x)) )
) {
    if (x <= 0) return;
    this_->x_ = x;
} BOOST_LOCAL_FUNCTION_END(unamed)
unamed();

I am not sure of the utility of unnamed local functions but if there
is a clear use case for them, they would be really trivial to
implement. I think what we need to find is a good use case for this.

I was thinking to provide `BOOST_BLOCK` for "symmetry" because I will
provide `BOOST_BLOCK_CONST` (as I said the use case for const-block is
to add the semantic information about const-correctness of the
enclosed instructions). I'll think about this more a propose something
if I can find a use case then reviewers of the library can propose
alternatives -- this stuff it's really trivial to implement around the
basic `BOOST_LOCAL_FUNCTION` macros.

> Concerning the 'default' values that you proposed, it is an interesting idea, though I am not sure I would have a use for it.

--
Lorenzo

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