Objective C blocks

B

Beej Jorgensen

Have you guys checked this out?

http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10

It describes a change to Objective C made by Apple to support anonymous
functions in C. The syntax is actually quite C-clean (unlike the usual
Objective C stuff) and my first impression is that it would be a welcome
addition to the language.

I guess they're submitting it for consideration.

What do you think, folks?

-Beej
 
R

REH

Have you guys checked this out?

http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10

It describes a change to Objective C made by Apple to support anonymous
functions in C.  The syntax is actually quite C-clean (unlike the usual
Objective C stuff) and my first impression is that it would be a welcome
addition to the language.

I guess they're submitting it for consideration.

What do you think, folks?

It is a little light on details. Do you know how it compares to the
lambdas being added to the next C++ standard? The apple solution looks
similar, using ^ instead of []. It doesn't explain the rules for
forming closures.

I've always like the GCC solution, myself. Although, I never use it
for portability's sake.

REH
 
R

Richard Tobin

Richard Heathfield said:
I was a bit hampered by having to look at the HTML rather than the
rendered page (ancient browser couldn't cope), but it did look quite
interesting. I'm not quite sure what it's supposed to buy me, though,
that I can't buy with function pointers.

Closures.

-- Richard
 
B

Beej Jorgensen

REH said:
I've always like the GCC solution, myself. Although, I never use it
for portability's sake.

What's GCC's solution? I'm hunting around, but not quite finding.
Nested functions? Or is there something else?

-Beej
 
R

REH

What's GCC's solution?  I'm hunting around, but not quite finding.
Nested functions?  Or is there something else?

I think it is deprecated (or even removed) by now. You nailed it. It
was nested functions. It just looked more natural than other solutions
I've seen (i.e., more like how Ada and Pascal does it, but they don't
support closures). I don't remember if GCC supported closures, but I
doubt it.

REH
 
B

Beej Jorgensen

REH said:
I don't remember if GCC supported closures, but I doubt it.

It looks like "sort of". The nested function could see the nester's
variables even when being called from elsewhere. However, according to
the docs (and this is an actual quote):

If you try to call the nested function through its address after the
containing function has exited, all hell will break loose.

--presumably because the nested function has ceased to exist. The real
question is: is "all hell will break loose" the actual defined behavior?
;)

But yes, RH--that's a topic for another place, though I am interested in
the concept in a general C sense.

-Beej
 
R

Richard Tobin

I don't remember if GCC supported closures, but I doubt it.
[/QUOTE]
It looks like "sort of". The nested function could see the nester's
variables even when being called from elsewhere. However, according to
the docs (and this is an actual quote):

If you try to call the nested function through its address after the
containing function has exited, all hell will break loose.

This is a decades-old issue. In the Lisp world it was known as the
"upward funargs" problem. Though full closures are more useful and
consistent, they are relatively expensive to implement - closed-over
local variables must be stored on the heap, and preferably garbage
collected somehow - and downward funargs are adequate for many
purposes.

-- Richard
 
R

Richard Tobin

Richard Heathfield said:
The funny thing about closures is that those who understand them can't
imagine life without them, whereas those who don't understand them
can't imagine what possible use they could be.

Amusing, but completely false. Everyone I know who understands
closures is also quite familiar with how to work around their absence
when using languages that don't provide them.

-- Richard
 
R

REH

It looks like "sort of".  The nested function could see the nester's
variables even when being called from elsewhere.  However, according to
the docs (and this is an actual quote):

  If you try to call the nested function through its address after the
  containing function has exited, all hell will break loose.

--presumably because the nested function has ceased to exist.  The real
question is: is "all hell will break loose" the actual defined behavior?
;)

But yes, RH--that's a topic for another place, though I am interested in
the concept in a general C sense.

Now, I remember. The GCC implementation was based off of this paper:

http://web.pdx.edu/~hegbloom/download/Usenix88-lexic.pdf

Although the paper targets C++, the GCC implementation supports C not C
++.

REH
 
B

Ben Bacarisse

Richard Heathfield said:
Why let the facts get in the way? Nobody else does. :)

Which facts are you thinking of? I thought your remark was just a
joke so I did not comment on it, but it (well one half of it
certainly) contradicts my experience as well.
 
S

Seebs

I think I remember an article by someone working for Apple, where they
figured out that the implementation for local functions used by gcc
would write code to memory and then execute it, so they couldn't turn
some security feature on newer Intel processors on and keep local
functions working at the same time. So they removed that feature from
their copy of the gcc compiler, and found a total of eight uses in all
the code that shipped with the then current version of MacOS X. So
they removed those eight local functions.

I have seen nested functions used in code intended to be used with gcc several
times.

I've never seen one that didn't strike me as revealing a fundamental failure
to understand the problem.

-s
 
R

Richard Bos

Closures.

Odd thing, that - closures are a very nifty _idea_, but I've never come
across a problem where I thought "you know, a closure would be just what
I should use here", except for sample cases especially contrived to show
off the niftiness of closures.

Richard
 
D

Default User

Richard said:
Odd thing, that - closures are a very nifty idea, but I've never come
across a problem where I thought "you know, a closure would be just
what I should use here", except for sample cases especially contrived
to show off the niftiness of closures.

Years ago, I worked with a C-derived language for programming MUD games
called LPC: <http://en.wikipedia.org/wiki/LPC_(programming_language)>

That had closures, and some of the programmers used them. I didn't in
any of my stuff, but I learned enough to be able to read other code
there.

I enjoyed that stint working on a MUD, and I still have some ideas, but
never have the time anymore. If EOTL is still going when I retire, I
might make a triumphant return.




Brian
 
R

Richard Tobin

Closures.
[/QUOTE]
Odd thing, that - closures are a very nifty _idea_, but I've never come
across a problem where I thought "you know, a closure would be just what
I should use here"

Well, it's one of those things where once you start thinking that way,
you see all kinds of uses for them.

But I think the most obvious case is callback functions. There are
any number of C APIs where you have to provide a function pointer and
a void * pointer which gets passed as an argument to it [1]. This is
a case where a closure is more elegant, more natural, and more
versatile.

It's interesting to see how this is done in some object oriented
languages that don't provide closures. You provide an instance of
some class that provides a certain method, and that method is called
on the instance. There is a symmetry between closures and objects: a
closure is a function with some associated data, and an object is some
data with associated functions.

[1] A typical example is the X Toolkit's widget callbacks:

void XtAddCallback(Widget w, String callback_name,
XtCallbackProc callback, XtPointer client_data);

-- Richard
 
N

Nick Keighley

Have you guys checked this out?

http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10

It describes a change to Objective C made by Apple to support anonymous
functions in C.  The syntax is actually quite C-clean (unlike the usual
Objective C stuff) and my first impression is that it would be a welcome
addition to the language.

I guess they're submitting it for consideration.

What do you think, folks?

interesting. Can it be implemented efficiently? At first glance it
looks
a bit un-C-like. I have cursed the fact that I have to pass parameters
as global variables when some callback function doesn't have enough
arguments. And I've written plany of little functions

int f2 (int n)
{
return 2 * f(n);
}

because f2 is used a lot.
 
N

Nick Keighley

Richard Bos said:
Odd thing, that - closures are a very nifty _idea_, but I've never come
across a problem where I thought "you know, a closure would be just what
I should use here"

Well, it's one of those things where once you start thinking that way,
you see all kinds of uses for them.

But I think the most obvious case is callback functions.  There are
any number of C APIs where you have to provide a function pointer and
a void * pointer which gets passed as an argument to it [1].  This is
a case where a closure is more elegant, more natural, and more
versatile.

It's interesting to see how this is done in some object oriented
languages that don't provide closures.  You provide an instance of
some class that provides a certain method, and that method is called
on the instance.

C++s functors do something like this
 There is a symmetry between closures and objects: a
closure is a function with some associated data, and an object is some
data with associated functions.

[1] A typical example is the X Toolkit's widget callbacks:

  void XtAddCallback(Widget w, String callback_name,
                     XtCallbackProc callback, XtPointer client_data);
 
B

Beej Jorgensen

Nick Keighley said:
interesting. Can it be implemented efficiently?

I think yes and no--when you want to do closure stuff after the
enclosing function falls out of scope, weird stuff happens.

I dug up some more links that talk about it in detail (the 2nd one might
be more appropriate for your question):

http://clang.llvm.org/docs/BlockLanguageSpec.txt
http://clang.llvm.org/docs/BlockImplementation.txt
http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-14-practical-blocks.html

-Beej
 
N

Nobody

Odd thing, that - closures are a very nifty _idea_, but I've never come
across a problem where I thought "you know, a closure would be just what
I should use here"

Well, it's one of those things where once you start thinking that way,
you see all kinds of uses for them.

But I think the most obvious case is callback functions. There are
any number of C APIs where you have to provide a function pointer and
a void * pointer which gets passed as an argument to it [1]. This is
a case where a closure is more elegant, more natural, and more
versatile.

Closures are more elegant, but ultimately anything you can do with a
closure you can do with a function pointer and a data pointer.

Of course, that doesn't help when the function forgets about the data
pointer (e.g. qsort).
 
M

Marco

[you probably should have mentioned that this is an Apple extension to
C as well as Objective C]

this is an interesting extension

=========================
the author has some example code as well

from C Blocks article
by Joachim Bengtsson
"
Variables pointing to blocks take on the exact same syntax as
variables pointing to functions, except * is substituted for ^. For
example, this is a function pointer to a function taking an int and
returning a float:

float (*myfuncptr)(int);
and this is a block pointer to a block taking an int and returning a
float:

float (^myblockptr)(int);

As with function pointers, you'll likely want to typedef those types,
as it can get relatively hairy otherwise. For example, a pointer to a
block returning a block taking a block would be something like void(^)
(void) (^myblockptr)(void(^)()), which is nigh impossible to read (and
doesn't even compile, I'm not sure how that'd be done). A simple
typedef later, and it's much simpler:

typedef void (^Block)();

Block (^myblockptr)(Block);

Declaring blocks themselves is where we get into the unknown, as it
doesn't really look like C, although they resemble function
declarations. Let's start with the basics:

myvar1 = ^ returntype (type arg1, type arg2, and so on) {
block contents;
like in a function;
return returnvalue;
};

This defines a block literal ( from after = to and including } ),
explicitly mentions its return type, an argument list, the block body,
a return statement, and assigns this literal to the variable myvar1.

A literal is a value that can be built at compile-time. An integer
literal (The 3 in int a = 3;) and a string literal (The "foobar" in
const char *b = "foobar";) are other examples of literals. The fact
that a block declaration is a literal is important later when we get
into memory management.

Finding a return statement in a block like this is vexing to some.
Does it return from the enclosing function, you may ask? No, it
returns a value that can be used by the caller of the block. See
'Calling blocks'. Note: If the block has multiple return statements,
they must return the same type.
"
 
T

Tim Rentsch

Richard Heathfield said:
The funny thing about closures is that those who understand them can't
imagine life without them, whereas those who don't understand them
can't imagine what possible use they could be.

So, pretty much like pointers, or recursion...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top