Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Blocks vs. C++ lambda's?

213 views
Skip to first unread message

Boris Dušek

unread,
Apr 30, 2009, 3:40:42 PM4/30/09
to
[submitted to comp.lang.c++.moderated as per suggestion [1], original
message on clang list here [2]]

Hi,

I learned about the blocks feature Apple is implementing as an
extension to C. After looking at it briefly, I concluded it's
basically the same thing as C++(0x) lambdas. But there should be a
difference since if not, (I guess) it would make sense to just adopt
the C++ lambda syntax in C and Obj-C to achieve the goal. So could
someone please point out what blocks provide that C++ lambdas do not
(and vice versa)?

Thanks,
Boris Du�ek

[first answer available at [3]]

[1]: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2009-April/004948.html
[2]: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2009-April/004946.html
[3]: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2009-April/004947.html


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Mathias Gaunard

unread,
May 1, 2009, 11:04:53 PM5/1/09
to
On 30 avr, 21:40, Boris Du�ek <boris.du...@gmail.com> wrote:
> [submitted to comp.lang.c++.moderated as per suggestion [1], original
> message on clang list here [2]]
>
> Hi,
>
> I learned about the blocks feature Apple is implementing as an
> extension to C. After looking at it briefly, I concluded it's
> basically the same thing as C++(0x) lambdas. But there should be a
> difference since if not, (I guess) it would make sense to just adopt
> the C++ lambda syntax in C and Obj-C to achieve the goal. So could
> someone please point out what blocks provide that C++ lambdas do not
> (and vice versa)?
>
> Thanks,
> Boris Du�ek
>
> [first answer available at [3]]
>
> [1]:http://lists.cs.uiuc.edu/pipermail/cfe-dev/2009-April/004948.html
> [2]:http://lists.cs.uiuc.edu/pipermail/cfe-dev/2009-April/004946.html
> [3]:http://lists.cs.uiuc.edu/pipermail/cfe-dev/2009-April/004947.html

Unlike what has been said in [3], there is a a short syntax with C++0x
lambdas to take every variable in scope by reference. ([&])
The type of a lambda is also unspecified, allowing potentially more
optimal code.

Now, when you look at Apple blocks, it will require __block specifiers
added to variables you want to modify (the very fact that this is
required suggests the whole system is defective).
Variables are taken by reference but then by value when the block
exits the scope (and the copied context necessarily lives on the heap,
it seems). A weird semantic that will only lead to broken designs, but
probably makes people that love GC happy. Without saying this probably
has quite the efficiency cost, of course, since this requires special
indirections.

It is claimed the C++0x lambdas syntax would break compatibility with
C programs, but I don't think that is true. There are probably other
problems to integrate it with C, though, mainly the fact that C can't
really deal with unspecified types and build type erasure.

Apple blocks is really just an ObjC feature they try to generalize to
other languages. For C++, the system designed for that language is
just so much better.

Boris Dušek

unread,
May 2, 2009, 9:45:52 AM5/2/09
to
On 2 Kvďż˝, 05:04, Mathias Gaunard <loufo...@gmail.com> wrote:
> Now, when you look at Apple blocks, it will require __block specifiers
> added to variables you want to modify (the very fact that this is
> required suggests the whole system is defective).
> Variables are taken by reference but then by value when the block
> exits the scope (and the copied context necessarily lives on the heap,
> it seems). A weird semantic that will only lead to broken designs, but

did you mean that if some local variable has __block marker, then it
should not have been declared as local variable in the first place,
and instead should have been declared in some "shared state struct" to
which the blocks would have access (through some pointer)? If yes,
that has been my thought as well.

SG

unread,
May 3, 2009, 12:19:52 PM5/3/09
to
On 30 Apr., 21:40, Boris Du�ek <boris.du...@gmail.com> wrote:
> I learned about the blocks feature Apple is implementing as an
> extension to C. After looking at it briefly, I concluded it's

Here's a link to a "blocks" specification:
http://clang.llvm.org/docs/BlockLanguageSpec.txt

> basically the same thing as C++(0x) lambdas. But there should be a
> difference since if not, (I guess) it would make sense to just adopt
> the C++ lambda syntax in C and Obj-C to achieve the goal. So could
> someone please point out what blocks provide that C++ lambdas do not
> (and vice versa)?

It seems they're similar but the "blocks" feature is more tailored to
C while the C++ lambda feature is more tailored to C++.

The C++ lambda syntax doesn't include a special class of nameable
types that can be used to store or refer to C++ lambda objects. But
you need something like this in order to pass those objects/references
around in C (i.e. call a function with a block as parameter). In C++
you don't need a special class of types for this. Lambda objects are
simply objects of some anonymous type which overrides the function
call operator. If you intent to use this object as parameter to
another function you have a choice between

(1) making the function a template so it can accept the lambda
objects directly (no indirection, inlining possible)
(2) making the function accept a parameter of some function<>
instance (indirection, no inlining possible)

Feature-wise, I think C++ lambdas are more powerful. You can easily
emulate "C blocks" with C++ lambdas wrapped in a polymorphic
function<> object. So, the C++ lambdas are more like a low level
feature whereas "C blocks" are a high level feature which includes
implicit memory and life-time management. To emulate this in C++0x you
could use a shared_ptr which is captured by value and refers to the
"__block" data. So, the following C code with "clang blocks"

// may store block for later use
void bar( int(^blk)(int) );

void foo() {
__block int x;
int factor;
x = 23;
factor = 3;
bar(^(int a){return x += a*factor;});
}

could be translated to this C++0x version

// may store function object for later use
void bar(function<int()> blk);

void foo() {
shared_ptr<int> px (new int);
*px = 23;
int factor = 3;
bar([=](int a){return *px += a*factor;});
}

as far as I can tell. But C++ also allows you to write something like
this:

int foo(vector<int> const& data) {
int accum = 0;
// The lambda object here doesn't outlive this scope
// so it's safe to capture by reference...
for_each(data.begin(),data.end(),[&](int x){accum+=x;});
return accum;
}

which doesn't involve any dynamic memory management w.r.t. the lambda
object and is potentially very fast (inlining of "accum+=x;"). If you
want to support this kind of syntax in C without templates you are
forced to implement this feature with an implicit level of
indirection. Unfortunately, this will remove the possible performance
advantage of lambda objects over function pointers in C++.

Cheers!
SG

0 new messages