Topic: question about anonymous functions in c++0x


Author: Brendan <catphive@catphive.net>
Date: Sat, 8 Sep 2007 09:48:20 CST
Raw View
Has anyone submitted nested and anonymous functions as a possible
extension for c++0x? What do people think of the syntax below?These
are obviously syntactic sugar changes, but they would make a *lot* of c
++ constructs much more readable in practice.

Let's say that func and closure are made keywords.

They would be very useful in conjunction with for_each and bind,
consider

If the expression
func (int arg1, int arg2, etc) {
  statements;
};

evaluates to a function pointer and doesn't generate an externally
linkable symbol. Then we can do something like

vector<int> v;
//populate v...

for_each(v.begin(), v.end(), func(int x) {
  cout << x;
}

//and using the tr1 construct bind...
int sum = 0;
for_each(v.begin(), v.end(), bind(func(int& sum, int x) {
  sum += x;
}, ref(sum)));

Which is quite a bit more terse than creating a function object, but
still a little awkward. It can be made more readable if an overload of
bind is made that accepts a tuple as it's first argument and a tr1
function as its second.
int sum = 0;
for_each(v.begin(), v.end(), bind(tie(sum), func(int& sum, int x) {
  sum += x;
}));

You could avoid the bind entirely if func is a lexical closure, where
enclosed variables are treated as references to the original, becoming

int sum = 0;
for_each(v.begin(), b.end(), closure(int x) {
  sum += x;
});

Which should return an anonymous, function object with internal
linkage. An anonymous function object as opposed to a function pointer
is necessary since nonstatic storage must exist to hold pointers to
the enclosing local and member variables referenced by the closure.
Note that since the function object is anonymous, to pass it to a
nontemplate function you need something like tr1 function which uses
external polymorphism.

The one mark against lexical closures is that it becomes easy to
accidentally reference state unintentionally. Closures are useful
during iteration, but you don't want them if you are going to return a
function, otherwise you risk unintentionally referencing local
variables. Consider:

// Note use of tr1 return type.
function<void()> factory_method_factory() {
  int i;
  // Intervening code that uses i.
  return closure() {
    // Forget to define i.
    while(i < 100) {
      cout << i;
      ++i;
    }
  };
}

This will compile with the closure syntax, even though it will trash
the stack. However, if func is used it will generate an appropriate
symbol not defined error and fail to compile. Thus, to avoid this sort
of error, programmers just need to remember that funcs are static and
thus are ok to pass around, return etc (or at least as safe as normal
function pointers and functors), but that closures should be treated
as if owned by the enclosing scope, and thus references should not be
returned.

Let me know what you think,
Brendan

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: jgottman@carolina.rr.com (Joe Gottman)
Date: Sun, 9 Sep 2007 05:12:03 GMT
Raw View
Brendan wrote:
> Has anyone submitted nested and anonymous functions as a possible
> extension for c++0x?

    They are called lambda functions.  Here is the most recent proposal:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2329.pdf .

Joe Gottman

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: nagle@animats.com (John Nagle)
Date: Mon, 10 Sep 2007 02:54:57 GMT
Raw View
Joe Gottman wrote:
> Brendan wrote:
>
>> Has anyone submitted nested and anonymous functions as a possible
>> extension for c++0x?
>
>
>    They are called lambda functions.  Here is the most recent proposal:
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2329.pdf .
>
> Joe Gottman

    That proposal includes closures, which are a nightmare in a language with
manual storage allocation.

    Ordinary nested functions have their uses, but taking C++ all the way
to closures is probably going too far.  We have Java and C# for that level
of dynamism.

    John Nagle
    Animats

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: l.j.persson@gmail.com (Jonas Persson)
Date: Mon, 10 Sep 2007 21:14:45 GMT
Raw View
John Nagle skrev:
>    That proposal includes closures, which are a nightmare in a language
> with manual storage allocation.
>
Can you expand on that? I've read the proposal and I cannot see anything
that resembles a nightmare. The issue of the local context goes out of
scope is no different from returning references to local variables. And
that is well known for all C++ users.

>    Ordinary nested functions have their uses, but taking C++ all the way
> to closures is probably going too far.  We have Java and C# for that level
> of dynamism.
Not in my C++ codebase I haven't;-) That it may be easier to implement
in java or C# shouldnt discorage us from doing it as perfect as possible
for C++.
Actually, my experience from C# delegates suggests that the proposed C++
model would be just good enough for most situations. I find access to
the local context to be very useful, but only for delegates that are
used locally(like stl predicates would in C++). But when the delegates
are stored away out of scope to be evaluated later, the local context is
mostly a source of bugs anyway, since it often produces unintentional
dependecies between delegates created in the same context.


 / Jonas

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Mon, 10 Sep 2007 21:56:21 CST
Raw View
On 10 Sep., 04:54, na...@animats.com (John Nagle) wrote:
> Joe Gottman wrote:
> >    They are called lambda functions.  Here is the most recent proposal:
> >http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2329.pdf.
>
>     That proposal includes closures, which are a nightmare in a language with
> manual storage allocation.
>
>     Ordinary nested functions have their uses, but taking C++ all the way
> to closures is probably going too far.  We have Java and C# for that level
> of dynamism.

The above quoted paper proposes two different techniques to realize
their "closures": Via the so-called <&> form the lambda functions are
simple and cheap stack-based entities w/o any free store in sight,
quite similar to (Turbo) Pascals "function of object", which have
simply
two pointers internally (The paper uses the notion of "static link"
here).

The other case is a representation similar to that of tr1::function,
which
also not necessarily uses allocated memory - usually there exists a
static memory buffer, which is used if sufficient and which switches
to
dynamical allocated memory, if not. I don't see any life-time
problems
here - I have worked for years with such closures in Turbo Pascal and
Delphi (which both use *no* garbage collection in their native forms)
without any problems.

Greetings from Bremen,

Daniel Kr   gler


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]