Re: Blocks in Obj-C (was: Passing Obj-C method as callback to C function)
Re: Blocks in Obj-C (was: Passing Obj-C method as callback to C function)
- Subject: Re: Blocks in Obj-C (was: Passing Obj-C method as callback to C function)
- From: Christian Brunschen <email@hidden>
- Date: Wed, 29 Oct 2003 18:00:51 +0100 (MET)
On Wed, 29 Oct 2003 email@hidden wrote:
>
On Oct 29, 2003, at 2:02 AM, Christian Brunschen wrote:
>
>
> The lack of a real need for Smalltalk-style Blocks, probably. After
>
> all,
>
> in Smalltalk, Blocks are needed for basic things like iteration,
>
> conditionals, etc. Objective-C, however, uses C's constructs for those,
>
> removing the need for Blocks.
>
>
Yes, but blocks are vastly superior for iteration. You don't have to
>
specify start and end conditions so you can't screw them up, plus there
>
are the query ops in Smalltalk collections like #select:, #collect:,
>
#detect: that have no analog presently. For instance:
>
>
result = [array select: @[:ea | ea intValue > 5]];
>
>
vs (off the top of my head - something like)
>
>
result = [NSMutableArray array];
>
NSEnumerator* i = [array objectEnumerator];
>
id item;
>
while(item = [i nextObject])
>
{
>
if([item intValue] > 5)
>
{
>
[result addObject: item];
>
}
>
}
Note that in your example above, the hand-written while loop actually
combines the functionality of the 'select:' method on the array, with the
functionality of the Block.
Iterating over a collection is really the only case where I think that
Blocks offer a relatively compelling advantage. However, I think that for
that kinds of uses one should take a close look at another context where
something similar is prevalent: Functional programming. And by looking at
the similarities I think that it quickly becomes apparent that what we
really want to use is a _function_, not a 'Block'. This can be fixed, of
course, by renaming 'Block' to 'Function' (as that is essentially what
a Block is - an anonymous function), or we can realize that we can just as
easily use a _C function_ for that purpose:
id checkGreaterThanFive(id arg) {
return [NSNumber numberWithBoolean:[id intValue] > 5];
}
NSArray *greaterThanFive = [array select:greaterThanFive];
where the 'select:' method would simply be accepting a C function pointer
rather then a Block pointer as its argument.
>
> Things like [array do:...] can actually be done differently, using
>
> concepts like Higher-Order Messaging.
>
>
Yes, I'm familiar with Marcel's library. And its really brilliant
>
considering the constraints he was working under. But in the above
>
example, it wouldn't help because HOM can only arrange to send a
>
message to each object and doesn't help if there's no method that does
>
what you want. You could stick one on using a category but now you've
>
written much more code than just doing it with C loops.
On the other hand, it becomes easier to reuse that code elsewhere, because
it is now available through actual methods rather than as anonymous Blocks
sprinkled throughout the code.
>
> And indeed anything you might want to use a Block for can actually be
>
> done
>
> using a plain C function. So we already _have_ a construct, and don't
>
> really need to introduce another one.
>
>
Yes, and you can fake a block in Java with an anonymous class
Actually, it's more a case of an anonymous inner class being the more
general concept, or of a Block being a special case of an anonymous inner
class with a specific set of entry points and with special syntactic
sugar.
>
- but it
>
takes too long to type all the extra crap, like making up a name,
>
naming the return type, etc...
Consider in Java,
public class Block : Object {
public Object value() { return null; }
public Object value(Object arg1) { return null; }
public Object value(Object arg1, Object arg2) { return null; }
}
You can now create an anonymous subclass of this Block class:
Bock myBlock = new Block() { public Object value() { return "foo"; } };
Your example could be rewritten as
NSArray greaterThanFive = NSArray.select(new Block(Object arg) {
public Object value() {
return new Boolean(((Integer)arg).intValue() > 5); }
This isn't really very much more code than the special Block syntax uses.
The main difference here is that you have to explicitly spell out the name
of the superclass of your anonymous class, as well as the name of the
method your are overriding. A bespoke Block syntax simply short-cuts those
two things for you, implicitly specifying that you are subclassing the
'Block' class and overriding the 'value', 'value:', or 'value:with:'
method depending on the number of arguments that your block declares.
The big difference here is that Blocks limit you to precisely that
superclass, and precisely those methods. If you have a generalized
anonymous class mechanism, you can use arbitrary superclasses and
arbitrary, even multiple, entry points.
>
> Many uses of Blocks also lead to a code clutter: code that serves one
>
> purpose being written within a method that actually does something
>
> else.
>
> In such cases I find it better to separate the code that would have
>
> beel
>
> placed in a Block, in a method or function of its own; this can then
>
> also
>
> be debugged and reused much more easily.
>
>
To each his own. I disagree. I think it would tend to keep the
>
namespace cleaner and makes the locality of the operation cleaner.
I think that largely depends on how exactly one uses the Blocks. Their
existance makes it possible to have a method that ostensably performs one
function, but which happens to contain the code - in the shape of a Block
- which does something else entirely. Of course, the same danger exists
with anonymous classes of any kind.
>
Thanks for your opinion though.
You can have my opinions any time ;)
>
-Todd Blanchard
Best wishes,
// Christian Brunschen
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.