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

{} vs. <>

0 views
Skip to first unread message

David Stes

unread,
Jul 30, 2000, 3:00:00 AM7/30/00
to

When I first saw the <> proposal I thought it was a good idea, but
thinking a couple of minutes about it, I'm not so sure...

A Block is anonymous method.

You can have a "named" method :

- mouse_entered { [window highlight];

and then set : [aControl onMouseEnter:@selector(mouse_entered)];

Now if you work with "anonymous" or unnamed methods :

immediately use : [aControl onMouseEnter: { [window highlight]; }];


So the motivation to use {} instead of some new syntax like <> is (and
remains) that what you basically do is "chop off" the name of the method
: you make it anonymous by removing the name and the keywords.

This just leaves you with the colons ':' and the braces {}

- mouse_entered:mouse location:point { if ([window intitle:point])
[window highlight]; }

If you make this method "anonymous" the procedure is to remove
"mouse_entered" and "location" and you get :

{ :mouse :point | if ([window intitle:point]) [window highlight]; }

introducing '|' (as in smalltalk) to separate arguments and body.

strictly speaking you would have :

:mouse :point { if([window intitle:point]) [window highlight]; }

as "anonymous" counterpart of the "named" method.

mike burrell

unread,
Jul 30, 2000, 3:00:00 AM7/30/00
to
David Stes <st...@pandora.be> wrote:
> A Block is anonymous method.

> Now if you work with "anonymous" or unnamed methods :

> immediately use : [aControl onMouseEnter: { [window highlight]; }];

> So the motivation to use {} instead of some new syntax like <> is (and
> remains) that what you basically do is "chop off" the name of the method
> : you make it anonymous by removing the name and the keywords.

> This just leaves you with the colons ':' and the braces {}

hmm this is interesting. this could be very easy to parse if nested
functions/methods were supported.

--
/"\ m i k e b u r r e l l
\ / ASCII RIBBON CAMPAIGN mik...@home.com
X AGAINST HTML MAIL,
/ \ AND NEWS TOO, dammit

David Stes

unread,
Jul 30, 2000, 3:00:00 AM7/30/00
to
mike burrell wrote:
>
> hmm this is interesting. this could be very easy to parse if nested
> functions/methods were supported.

Blocks are somewhat like nested function/methods, because you can have
a method and then inside that method a "Block", which is like an
anonymous method "nested" in the enclosing method.

But a Block is more powerful because it is an object (responds to the
messages of the Object class) and can be added to Set, OrderedCollection
and so on.

You can have an instance method :

- onMouseEnter:aBlock {
mouseEnterAction = aBlock;
return self;
}


and then 'aBlock' could be evaluated, even when the function that has
created the block has exited...

Marcel Weiher

unread,
Jul 30, 2000, 3:00:00 AM7/30/00
to
David Stes <st...@pandora.be> writes:


>When I first saw the <> proposal I thought it was a good idea, but
>thinking a couple of minutes about it, I'm not so sure...

>A Block is anonymous method.

>You can have a "named" method :

> - mouse_entered { [window highlight];

> and then set : [aControl onMouseEnter:@selector(mouse_entered)];

>Now if you work with "anonymous" or unnamed methods :

> immediately use : [aControl onMouseEnter: { [window highlight]; }];


>So the motivation to use {} instead of some new syntax like <> is (and
>remains) that what you basically do is "chop off" the name of the method
>: you make it anonymous by removing the name and the keywords.

>This just leaves you with the colons ':' and the braces {}

> - mouse_entered:mouse location:point { if ([window intitle:point])
>[window highlight]; }

>If you make this method "anonymous" the procedure is to remove
>"mouse_entered" and "location" and you get :

> { :mouse :point | if ([window intitle:point]) [window highlight]; }

>introducing '|' (as in smalltalk) to separate arguments and body.

>strictly speaking you would have :

> :mouse :point { if([window intitle:point]) [window highlight]; }

Seeing all this: maybe it is "better" to simply define a method
and be done with it?

I thought long and hard about doing blocks before doing higher
order messages instead. I found that (a) longer blocks typically
deserved to be real methods, entities with *names* that can be
intention-revealing and ready for reuse and (b) shorter blocks
almost always turned out to be simple message sends (or be
replacable by simple message sends).

I've also done a fairly extensive (if ad-hoc) analysis of Smalltalk
code and found that most blocks there also fall into these two
categories, except for control structures, which in ST are also
implemented using blocks. However, in Objective-C we already
have control structures.

I'm not saying *all* constructs can be handled using higher order
messaging, just enough of them that introducing a somewhat difficult
language extension to deal with the few remaining does not seem
worthwhile to me.

(Anybody questioning that blocks are difficult should look at the
tons of papers that have been written on block-implementations in
Smalltalk)

Marcel
--

Java and C++ make you think that the new ideas are like the old ones.
Java is the most distressing thing to hit computing since MS-DOS.
- Alan Kay -

David Stes

unread,
Jul 30, 2000, 3:00:00 AM7/30/00
to
Marcel Weiher wrote:
>
> Seeing all this: maybe it is "better" to simply define a method
> and be done with it?

Of course not. You can replace messaging also by a function _msg() and
manually send messages by calling a function. You can do that, but it
is not a good idea.

Good, convenient, syntax is also important.

So [foo bar] is easier to write and deal with (understand) than
_msg(foo,bar) that you would insert in your program.

The same is true for Blocks.

id httpserver = [model httpserver];
[textfield onReturn: { [httpserver download:[textfield value]]; }];

for example when the user hits "enter" or "return" in a textfield, it
will evaluate the Block.

you can do these things also with functions, function pointers, and so
on.

But Blocks, just as messages, are convenient and important syntactical
language improvements.


Blocks are implemented in the POC (http://objc.sourceforge.net).

I think Blocks are about 50% of the Objective-C language and messaging
the other half.

Together those 2 concepts make up the bulk of the Objective-C language.

Blocks are as important as messaging itself it.

Ken Walter

unread,
Jul 30, 2000, 3:00:00 AM7/30/00
to
On Sun, 30 Jul 2000 11:29:21, David Stes <st...@pandora.be> wrote:

#
#When I first saw the <> proposal I thought it was a good idea, but
#thinking a couple of minutes about it, I'm not so sure...
#

I have found that any programming language that doe not keep
the set of operators a disjoint from the set of syntatic delimiters
leads to programming errors! Since I assume O-C has compares like <
then using < and > as a delimiter I consider very bad design!
I consider C++ the worst syntatically designed language around.

Ken Walter

Remove -zamboni to reply
All the above is hearsay and the opinion of no one in particular


David Stes

unread,
Jul 30, 2000, 3:00:00 AM7/30/00
to
Ken Walter wrote:
>
> Since I assume O-C has compares like <
> then using < and > as a delimiter I consider very bad design!

Let's simply continue to use {} for Blocks.

Besides, there's several POC users around, who now have programs with
the {} syntax, so I don't like to change this.

The {} syntax fits C and Objective-C rather nicely.

Marcel Weiher

unread,
Jul 30, 2000, 3:00:00 AM7/30/00
to
David Stes <st...@pandora.be> writes:

>Marcel Weiher wrote:
>>
>> Seeing all this: maybe it is "better" to simply define a method
>> and be done with it?

>Of course not. You can replace messaging also by a function _msg() and
>manually send messages by calling a function. You can do that, but it
>is not a good idea.

I did not propose that.

>Good, convenient, syntax is also important.

Yes, exactly! Convenient syntax was one of my main motivations in
creating HO-messaging, and the syntax is certainly more convenient
than blocks for the cases it covers.

>So [foo bar] is easier to write and deal with (understand) than
>_msg(foo,bar) that you would insert in your program.

Yes, and (Smalltalk syntax) 'foo do bar' is easier to deal with
than 'foo do:[ :each | each bar]', by a long shot (and there are
much better examples).

[..]

>I think Blocks are about 50% of the Objective-C language and messaging
>the other half.

My point is that messaging can take care of 99.9% of the things you'd
want blocks for.

>Together those 2 concepts make up the bulk of the Objective-C language.

I think you're pretty alone with that assertion.

>Blocks are as important as messaging itself it.

Ditto.

David Stes

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
Marcel Weiher wrote:
>
> >Good, convenient, syntax is also important.
>
> Yes, exactly! Convenient syntax was one of my main motivations in
> creating HO-messaging, and the syntax is certainly more convenient
> than blocks for the cases it covers.


The {} syntax is natural.

A compound statement, a series of statements, is delimited in C by
curly braces.

So are Objective-C Blocks : id myBlock = {
statement;statement;statement; };

This is also why I think it's not much of a problem that [] (which is
used in Smalltalk for a Block) is not available in Objective-C.

myObject do: [ foo bar. ]. from Smalltalk becomes :

[myObject do: { [foo bar]; }]; in Objective-C

The use of {} is very natural given the fact that compound statements
in C use curly braces. And given the fact that the body of a method is
also delimited by curly braces.

A Block, being a anonymous method, should be delimited by braces, just
as a named method.

--
David Stes Molenstraat 5 B-2018 Antwerpen, Vlaanderen, Belgie
Tel +32 3 237 43 54 Fax +32 3 237 40 76 Email st...@pandora.be

Stephen Peters

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

> Marcel Weiher wrote:
> >
> > >Good, convenient, syntax is also important.
> >
> > Yes, exactly! Convenient syntax was one of my main motivations in
> > creating HO-messaging, and the syntax is certainly more convenient
> > than blocks for the cases it covers.
>
>

> The {} syntax is natural. [...]


> A Block, being a anonymous method, should be delimited by braces,
> just as a named method.

I agree -- and if we were only talking about methods with no arguments
I'd be quite happy. But the arg passing syntax using what I keep
reading as an OR symbol (|) is something I find extremely jarring. I
realize that it has a well-known ancestry, but I don't find "it works
that way in Smalltalk" to be a compelling reason for a syntax change.

I still prefer Marcel's HO-messaging design, since it involves no
(IMHO) jarring syntax additions.

--
Stephen L. Peters por...@ai.mit.edu
PGP fingerprint: A1BF 5A81 03E7 47CE 71E0 3BD4 8DA6 9268 5BB6 4BBE
"Poodle: The other white meat." -- Sherman, Sherman's Lagoon

David Stes

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
Stephen Peters wrote:
>
> I still prefer Marcel's HO-messaging design, since it involves no
> (IMHO) jarring syntax additions.

What jarring ?

I find Blocks simplify a lot, with a clear and natural syntax.

For example a lot of Objective-C code is reading :

for(i=0,totalsize=0;i<n;i++) { totalsize += [[collection at:i] size]; }

while the equivalent with Blocks is easier and you don't have to declare
a loop variable.

[collection do:{ :each | totalsize += [each size]; }];

In addition, as I've said, because Objective-C Blocks as implemented in
Taskmaster and as implemented in the Portable Object Compiler, are not
"LIFO", you can also save Blocks in other objects (in collections, or as
instance variables of some class).

So you can have a instance variable of a class :

id mouseEnterBlock;

to save the action that should be done (what Block should be evaluated)
when the mouse pointers enters the viewable area of a control, for
instance.

Marcel Weiher

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

>Marcel Weiher wrote:
>>
>> >Good, convenient, syntax is also important.
>>
>> Yes, exactly! Convenient syntax was one of my main motivations in
>> creating HO-messaging, and the syntax is certainly more convenient
>> than blocks for the cases it covers.

>The {} syntax is natural.

The plain messaging syntax is even more natural.


> myObject do: [ foo bar. ]. from Smalltalk becomes :

> [myObject do: { [foo bar]; }]; in Objective-C

This example seems non-sensical to me because you aren't
using the object argument from the "do" iteration but
instead messaging a completely unrelated object.

Once again, I find:

[[myCollection do] bar];

even better, especially since it also allows *very* natural
expression of more complex messages, for example:

[@"Prefix" stringByAppendingString:suffix];
->
[[@"Prefix" collect] stringByAppendingString:[suffixes each]];
vs.
[suffixes collect:{ :each | @"Prefix"stringByAppendingString:each}];

or even:

[[myPrefixes collect] stringByAppendingString:[suffixes each]];

which cannot easily be expressed using blocks without introducing
helper constructs.

> The use of {} is very natural given the fact that compound statements
>in C use curly braces. And given the fact that the body of a method is
>also delimited by curly braces.

Yes, the {} syntax is OK . I am debating wether blocks are necessary.
From my Squeak experience, I have to say that they are not necessary in
Objective-C, HO-messaging can do most of what you need blocks for and
the rest can be handled by other means.

> A Block, being a anonymous method, should be delimited by braces, just
>as a named method.

Sure, if it is supposed to exist at all... :-)

Marcel Weiher

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

[storing blocks in instance variables]

>So you can have a instance variable of a class :

> id mouseEnterBlock;

>to save the action that should be done (what Block should be evaluated)
>when the mouse pointers enters the viewable area of a control, for
>instance.

I find storing a message to be sent to an object a much more cleaner,
much more "OO" approach for that sort of thing.

David Stes

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
Marcel Weiher wrote:
>
> Yes, the {} syntax is OK . I am debating wether blocks are necessary.

OK, so let's specify that IF the compiler supports Blocks, then it
should use the {} syntax.

Stephen Peters

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

> Stephen Peters wrote:
> >
> > I still prefer Marcel's HO-messaging design, since it involves no
> > (IMHO) jarring syntax additions.
>
> What jarring ?

I explained earlier in my message what I found jarring about the
blocks syntax, David. I try to read the entire text of your messages;
I'd appreciate it if you'd return the favor.

> I find Blocks simplify a lot, with a clear and natural syntax.

I agree. And we need something that

>
> For example a lot of Objective-C code is reading :
>
> for(i=0,totalsize=0;i<n;i++) { totalsize += [[collection at:i] size]; }
>
> while the equivalent with Blocks is easier and you don't have to declare
> a loop variable.
>
> [collection do:{ :each | totalsize += [each size]; }];

And the equivalent in HO-messaging is along the lines of (if I
understand Marcel's syntax properly, and using an object for the
collector):

[ [totalsize collect] sum: [collection each] ];

Again, I agree that blocks are an improvement over the baseline O-C
code; I'm just not convinced that they're necessarily the way to go --
especially if most of the same functionality can appear without a
syntactic change to what is considered "baseline Objective-C".

> In addition, as I've said, because Objective-C Blocks as implemented in
> Taskmaster and as implemented in the Portable Object Compiler, are not
> "LIFO", you can also save Blocks in other objects (in collections, or as
> instance variables of some class).

That's nice, but it actually doesn't bear on my syntactical qualms.

David Stes

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
Marcel Weiher wrote:
>
> >So you can have a instance variable of a class :
>
> > id mouseEnterBlock;
>
> >to save the action that should be done (what Block should be evaluated)
> >when the mouse pointers enters the viewable area of a control, for
> >instance.
>
> I find storing a message to be sent to an object a much more cleaner,
> much more "OO" approach for that sort of thing.


I find it much more object-oriented to store a Block in an instance
variable :-)

For example, you can have the following :

[myButton onClick:{ [window startFlashing]; }];

The method is implemented :

- onClick:aBlock { clickBlock = aBlock;return self; }

and when the user clicks the button, it would do :

[clickBlock value];

to evaluate the clickBlock. It can also have doubleClickBlocks and so
on.

Marcel Weiher

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

>Marcel Weiher wrote:
>>
>> Yes, the {} syntax is OK . I am debating wether blocks are necessary.

>OK, so let's specify that IF the compiler supports Blocks, then it
>should use the {} syntax.

Fine!

David Stes

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
Marcel Weiher wrote:
>
> >> Yes, the {} syntax is OK . I am debating wether blocks are necessary.
>
> >OK, so let's specify that IF the compiler supports Blocks, then it
> >should use the {} syntax.
>
> Fine!


I agree. We agree.

Marcel Weiher

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

>Marcel Weiher wrote:

>> I find storing a message to be sent to an object a much more cleaner,
>> much more "OO" approach for that sort of thing.

>I find it much more object-oriented to store a Block in an instance
>variable :-)

Although tastes differ, I don't understand how an anonymous function
with arbitrary code is more object-oriented than sending a message
to an object.

You might find it "cooler" or "better" or even "more flexible", but
"more object oriented"?

>For example, you can have the following :

> [myButton onClick:{ [window startFlashing]; }];

[myButton onClickSend:@selector(startFlashing) to:window];

>The method is implemented :

> - onClick:aBlock { clickBlock = aBlock;return self; }

-(void)onClick:(SEL)sel to:target
{
[self setClickSelector:sel];
[self setClickTarget:target];
}

>and when the user clicks the button, it would do :

> [clickBlock value];

[[self clickTarget] performMessage:[self clickSelector]]

>to evaluate the clickBlock. It can also have doubleClickBlocks and so
>on.

...

David Stes

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
Marcel Weiher wrote:
>
> You might find it "cooler" or "better" or even "more flexible", but
> "more object oriented"?

Of course it is more object oriented.

A Block is an object. It is in an instance of the class Block, which is
a subclass of Object.

You can save a Block in an "id" instance variable. You can add such
objects to collections of objects, such as Sets or Bags or Dictionaries.

Marcel Weiher

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

>Marcel Weiher wrote:
>>
>> You might find it "cooler" or "better" or even "more flexible", but
>> "more object oriented"?

>Of course it is more object oriented.

Yeah, right. An anonymous function is really object oriented.
By that token, the most OO languages are FP langauges.

>A Block is an object. It is in an instance of the class Block, which is
>a subclass of Object.

You are confusing concepts with implementation.

>You can save a Block in an "id" instance variable. You can add such
>objects to collections of objects, such as Sets or Bags or Dictionaries.

Have you tried archiving a block to disk, or sending it over a network
connection? Oops. The fact that you can wrap an object around an
anonymous functions does not suddenly make the concept object oriented.

David Stes

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
Marcel Weiher wrote:
>
> The fact that you can wrap an object around an
> anonymous functions does not suddenly make the concept object oriented.


Blocks are very object-oriented.

The defining property of an Objective-C object is that it has an "isa"
field that identifies the class that the object is an instance of.

In the case of Blocks, the "isa" field points to the class "Block".

So, I write something like :

[ slider onDrag: { [textfield text:[slider str]]; }];

and what happens is that the compiler creates an object whose "isa"
field is set to "Block" (the class) and whose contents is a function
pointer.

If the Block instance gets a -value message, then the function pointer
is dereferenced. This means that the code

[textfield text:[slider str]];

is evaluated.

Marcel Weiher

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

>Marcel Weiher wrote:
>>
>> The fact that you can wrap an object around an
>> anonymous functions does not suddenly make the concept object oriented.

>Blocks are very object-oriented.

[one more example snipped]

You keep asserting this, but you haven't addressed a single one of
the points I've raised.

Once again: I *know* that blocks are *implemented* as objects.
That does not change the fact that they are anonymous *funtions*,
which are, conceptually, very different beasts.

Do you understand why I am saying this? At all?

David Stes

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
Marcel Weiher wrote:
>
> That does not change the fact that they are anonymous *funtions*,
> which are, conceptually, very different beasts.

They're anonymous *methods* not *functions*.

Marcel Weiher

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
David Stes <st...@pandora.be> writes:

>Marcel Weiher wrote:
>>
>> That does not change the fact that they are anonymous *funtions*,
>> which are, conceptually, very different beasts.

>They're anonymous *methods* not *functions*.

Well, if you check the output of your translator, you will find
that Objective-C methods turn out to be C functions. What makes
them different from C functions? Nothing really, except that
they are given a *name* (the message name) under which they
can be accessed via the messaging function.

You will notice that *anonymous* 'methods' do not have such
a name...per definition. Guess what is left... :-)

Jason "Dickie" Martin

unread,
Jul 31, 2000, 3:00:00 AM7/31/00
to
hey marcel.. could you be a sport and post your higher-level messaging
syntax? i can't take a side if i dont know what you're talking about :)

jason


Lee Willis

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
One man's opinion:

I learned Objective-C years before I learned Smalltalk.

I haven't used Obj-C blocks yet, but my first take on it was similar to the
reactions here - Yuck, what a strange syntax / concept. It doesn't 'read'
well. This came before I knew Smalltalk.

But now, after having done some Smalltalk programming, I like Obj-C blocks.
And I find the rationale behind the {} syntax to be straightforward.

Does everyone remember the very first time you encountered the [] syntax for
messaging? Every person I've known (including myself) disliked it at first
glance. But quickly not only got used to it but became enamored with it. I
think the block {} notation is the same thing.

Lee Willis


Marcel Weiher

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
"Jason \"Dickie\" Martin" <ja...@joshs.com> writes:

>hey marcel.. could you be a sport and post your higher-level messaging
>syntax? i can't take a side if i dont know what you're talking about :)

Sure, the syntax is easy: it just consists of plain message sends.
The way it 'looks' is as if you're sending a 'prefix' message and
then the message you want to be handled specially.

The current 'prefix' messages I've implemented are those corresponding
to a subset of the Smalltalk collection iteration protocol:

-do send the message, no return
-collect gather the results of sending the message (in an NSArray)
-select gather the objects that return YES (non-nil...)
-reject gather the objects that return NO (nil)

Example uses:

I have an instance variable called "slots" that is an array. For some
strange reason, these contain objects that all have an instance variable
called 'original' and I want to clear this instance variable:

[[slots do] setOriginal:nil];

A classic is having an array of objects and wanting to put these
objects into a dictionary indexed by one of the attributes of
the objects, let's say the attribute 'key'.

[NSDictionary dictionaryWithObjects:objects forKeys:[[objects collect] key]]

Getting an array of attributes (without necessarily wanting to use it
as keys for a dictionary is generally a common idiom.

images = [[[self subobjects] collect] image]

Sometimes, these are nested:

[[[[activeReplacements collect] source] collect] replacementKey]

Another common idiom is maping an array "through" a dictionary. For
this purpose I have implemented a method called -map:aDict that
essentially returns [aDict objectForKey:self].

For example mapping color names to values:

id colorValues = [[colorNames collect] map:colorMap]

What follows is probably the longest expression I've used so far.
The purpose is to have a write some procedure-sets to a Postscript-
generation stream. The names of the procsets to add are returned
by a message unsurprisingly named -namesOfProcsetsToAdd. For
each of the procset-names, you then have to load the corresponding
procset (which resides in the bundle) using -frameworkResource:category:


[[target do] writeObject:[[[self collect] frameworkResource:[[self namesOfProcsetsToAdd] each] category:@"procset"] each]]

From the inside out:

[self namesOfProcsetsToAdd] // returns an array of strings
[... each] // returns an enumerator
[self frameworkResource:resourceName category:categoryName]
// returns NSData with the resource
[[self collect] frameworkResource:[[self namesOfProcsetsToAdd] each]
category:@"procset"
// This sends [self frameworkResource:name category:@"procset"]
// for each of the 'name' elements in -namesOfProcsetsToAdd
// It is an 'interesting' expression because it shows how
// some of the arguments of a HO message expression can vary
// while others stay fixed, and the parts that vary do not
// have to include the receiver (which in this case is 'self')
//
// How does the HO-framework figure out which arguments to
// the message expression vary and which stay fixed?
// -> Enumerators
// An enumerator is assumed to want to vary, everything else
// is not (except for receivers that are collections)

[target writeObject:anObject]

// write 'anObject' to the target, which is a stream-like entity

[[target do] writeObject:[... each]]

// send [target writeObject:anObject] for each object in [... each]

I hope these examples shed a little light, if not, feel free to ask!

Helge Hess

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to Marcel Weiher
Marcel Weiher wrote:
> >You can save a Block in an "id" instance variable. You can add such
> >objects to collections of objects, such as Sets or Bags or Dictionaries.
>
> Have you tried archiving a block to disk, or sending it over a network
> connection? Oops. The fact that you can wrap an object around an

> anonymous functions does not suddenly make the concept object oriented.

I can't see why this shouldn't be possible ?! The frames can be archived
and the code can be added as well. That ObjC compiles the code
complicates the procedure but it certainly is possible.

BTW I do not agree that blocks are anonymous functions (though I first
thought that they are implemented that way in POC, which isn't true).
IMHO the OO thing about blocks is that they have state (more
specifically, the associates frames) ! To me blocks are objects, since
they have the properties of an object, that is - they belong to a class,
they have behaviour and they own specific state. IMHO blocks are *very*
OO since they extend code to be objects as well.

Besides that I still think that the advantage of blocks is that they
operate in the context of the callee and therefore can access state at
this side. Using HO messaging I would need to pass every state the block
needs to access using a parameter (the infamous 'context' object ...).
IMHO blocks would be a really great addition to ObjC, but I heavily
doubt that they can be usefully implemented in a non-GC ObjC
environment.

Greetings
Helge

Marcel Weiher

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
"Lee Willis" <lee-w...@home.com> writes:

>One man's opinion:

>I learned Objective-C years before I learned Smalltalk.

Same here.

>I haven't used Obj-C blocks yet, but my first take on it was similar to the
>reactions here - Yuck, what a strange syntax / concept. It doesn't 'read'
>well. This came before I knew Smalltalk.

For me, it came after I knew Smalltalk.

>But now, after having done some Smalltalk programming, I like Obj-C blocks.
>And I find the rationale behind the {} syntax to be straightforward.

I also find the rationale for {} straightforward. However, I had seen
the original 'FP' notation before I encountered the use of blocks in
Smalltalk's collection protocol. It deals with combinations of pure
functions, thus allowing a much higher level of abstraction than
dealing with individual elements.

I was somewhat disappointed with the Smalltalk collection protocols
because although they had messages for iterating over entire collections
with user-defined operations (like map() or fold() ), the block-mechanism
destroyed the abstraction of dealing with the entire collection at
once by re-introducing the individial element.

There was always that annoying [ :each | each ... ]. Not only
annoying because it is just syntactic overhead in many cases,
but also because it destroyed the abstraction.

>Does everyone remember the very first time you encountered the [] syntax for
>messaging? Every person I've known (including myself) disliked it at first
>glance. But quickly not only got used to it but became enamored with it. I
>think the block {} notation is the same thing.

I have a question: do you think this is specifically *blocks* that you
grew fond of, or mroe generally having some sort of reasonably
convenient higher-order mechanism?

Marcel Weiher

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
Helge Hess <helge...@skyrix.com> writes:

>Marcel Weiher wrote:
>> >You can save a Block in an "id" instance variable. You can add such
>> >objects to collections of objects, such as Sets or Bags or Dictionaries.
>>
>> Have you tried archiving a block to disk, or sending it over a network
>> connection? Oops. The fact that you can wrap an object around an
>> anonymous functions does not suddenly make the concept object oriented.

>I can't see why this shouldn't be possible ?! The frames can be archived
>and the code can be added as well.

You are going to dump machine-code from one running process to disk,
unarchive it in a different process and except it to work?

>That ObjC compiles the code
>complicates the procedure but it certainly is possible.

Go ahead! :-)

>BTW I do not agree that blocks are anonymous functions (though I first
>thought that they are implemented that way in POC, which isn't true).

I don't think I said they "are" anonymous functions. They *implement*
the concept of anynoymous functions.

>IMHO the OO thing about blocks is that they have state (more
>specifically, the associates frames) !

That's an 'intersting' view.

>To me blocks are objects, since
>they have the properties of an object, that is - they belong to a class,
>they have behaviour and they own specific state. IMHO blocks are *very*
>OO since they extend code to be objects as well.

You are arguing on a different level, the implementation level, just
like David. What I am saying is this: a message send vs. an anonymous
chunk of arbitrary code. Which do you consider OO?

>Besides that I still think that the advantage of blocks is that they
>operate in the context of the callee and therefore can access state at
>this side.

This is one of the features I find much too powerful and unstructured.
It's like having *hidden* global variables. Yuck.

>Using HO messaging I would need to pass every state the block
>needs to access using a parameter (the infamous 'context' object ...).

Actually, that is a problem of blocks, not of HO-messages, because
HO-messages are just messages, they already have these parameters.
Having explicit parameters to methods vs. implicitly munging on
state was generally considered a "good thing" last time I checked.

Christian Brunschen

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
In article <3985E21C...@pandora.be>, David Stes <st...@pandora.be> wrote:
>Marcel Weiher wrote:
>>
>> That does not change the fact that they are anonymous *funtions*,
>> which are, conceptually, very different beasts.
>
>They're anonymous *methods* not *functions*.

In what way are they 'methods' rather than 'functions'?

I consider that the word 'method' is only really useful when referring to
a function that is defined on an object; not a stand-alone function. So, a
method is one of multiple possible entry-points to the functionality of a
given object.

Blocks, however, have _one_ entry point ... much like _any_ function, and
there's not much object-oriented about that.

Specifically, your use of blocks to specify what should happen on a given
action is really no different from specifying a callback function - except
that your callback function is 'wrapped' in an object. Whereas the
approach of specifying a target object and a selector to call on that
object adds a that extra object-oriented touch: rather than calling a
function (or block) and passing it an argument, you are calling a
specified method on a specified object.

I do not see how you can claim that blocks are 'more object-oriented' than
target-action , or higher-order messaging.

>--
>David Stes Molenstraat 5 B-2018 Antwerpen, Vlaanderen, Belgie
>Tel +32 3 237 43 54 Fax +32 3 237 40 76 Email st...@pandora.be

// Christian Brunschen


John C. Randolph

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to

Marcel Weiher wrote:
>
> "Jason \"Dickie\" Martin" <ja...@joshs.com> writes:
>
> >hey marcel.. could you be a sport and post your higher-level messaging
> >syntax? i can't take a side if i dont know what you're talking about :)
>
> Sure, the syntax is easy: it just consists of plain message sends.
> The way it 'looks' is as if you're sending a 'prefix' message and
> then the message you want to be handled specially.
>
> The current 'prefix' messages I've implemented are those corresponding
> to a subset of the Smalltalk collection iteration protocol:

Hmm.. Any plans to implement the rest of that protocol?

> -do send the message, no return

Isn't this equivalent to -makeObjectsPerform:?

> -collect gather the results of sending the message (in an NSArray)

This sounds like my -arrayByPickingWithSelector: method. I think it
might be advantageous to implement it separately for NSSet and the other
collection classes, since when I pick members of a set, I probably don't
care about their order, and would just as soon get the results back in a
set instead of an array.

> -select gather the objects that return YES (non-nil...)

I think I did this with my arrayByPickingWithSelector: method, and my
selectiveEnumerator class. Selective enumerators are initialized with a
collection and a selector, and each call to -nextObject returns the next
one that returned YES when sent the method called out by the selector.

> -reject gather the objects that return NO (nil)

Gee, I never needed this one ;-)

> Example uses:

[Marcel's examples snipped]

So, would it be correct to do the following to get all panels in an app?

NSArray * myPanels =
[[[NSApplication sharedInstance]
windowList]
collect]
isKindOfClass:[NSPanel class]];

I think I like this.

-jcr

Marcel Weiher

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
c...@df.lth.se (Christian Brunschen) writes:

>>They're anonymous *methods* not *functions*.

>In what way are they 'methods' rather than 'functions'?

>I consider that the word 'method' is only really useful when referring to
>a function that is defined on an object; not a stand-alone function. So, a
>method is one of multiple possible entry-points to the functionality of a
>given object.

And you have different implementations of the same method, all accessible
via the same name but from different objects.

>Blocks, however, have _one_ entry point ... much like _any_ function, and
>there's not much object-oriented about that.

Exactly.

>Specifically, your use of blocks to specify what should happen on a given
>action is really no different from specifying a callback function - except
>that your callback function is 'wrapped' in an object. Whereas the
>approach of specifying a target object and a selector to call on that
>object adds a that extra object-oriented touch: rather than calling a
>function (or block) and passing it an argument, you are calling a
>specified method on a specified object.

I'd prefer "sending a message to a specified object" :-) Anyway,
this also enables things like the responder-chain, where handlers
pass the message on until one actually does handle it. I don't
see how that sort of architecture would jive with ad-hoc handler
blocks.

It is interesting to note that this is a classic example of trying
to move forward and finding that you have returned to the beginning:

First, you have plain functions, and you need 'call-backs' and code
generation and have lots of little snippets of fairly anonymous
code acting as glue.

Then you abstract a little and get messages and methods, meaning
you can do something like a delegate, where you send a specific
message like before, but now the object can vary, and due to the
wonders of dynamic messaging you get different code executed
without generating code. This is what happens with the low
level events in AppKit, such as -mouseDown: etc.

Then you abstract a little further, by making the message to
be sent variable, and you get something like target/action, so
you can now send a specific message, which is an improvement
because you can wire directly ot specific actions, instead
of having to have intermediary code that converts from the
UI-message to the action-message. The glue-code has now
disappeared almost completey into the frameworks. This
is what controls do in AppKit.

Then you generalize that even further by noting "why just
a single target action, why not several" and you get something
like blocks. This looks even better, even more flexible, but
it turns out that you're back to where you started, having
lots of glue code flying around, except that they now live
in blocks.

>I do not see how you can claim that blocks are 'more object-oriented' than
>target-action , or higher-order messaging.

I have to admit that I started this by saying blocks are "less OO"... :-)

Marcel Weiher

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
"John C. Randolph" <j...@idiom.com> writes:

[HOM currently implements subset of ST collection protocol]

>Hmm.. Any plans to implement the rest of that protocol?

Only as the need arises (where 'need' is a flexible term...)

>> -do send the message, no return

>Isn't this equivalent to -makeObjectsPerform:?

Yes, roughly speaking. The difference is that one form suffices for
all potential messages with however many arguments, with any mix
of varying and non-varying arguments. I also think the syntax
is more 'natural' (that was one of the motivations).

[[slots do] setOrignal:nil]
vs.
[slots makeObjectsPerform:@selector(setOriginal:) withObject:nil]

or
[[slots do] setOriginal:[originals each]]
vs.
?

or
[[myDatabase do] storeObject:[myCommitList each]];
vs.
?


>> -collect gather the results of sending the message (in an NSArray)

>This sounds like my -arrayByPickingWithSelector: method.

Actually, -filterWithSelector: was the original... :-)

> I think it
>might be advantageous to implement it separately for NSSet and the other
>collection classes, since when I pick members of a set, I probably don't
>care about their order, and would just as soon get the results back in a
>set instead of an array.

Sure.

>> -select gather the objects that return YES (non-nil...)

>I think I did this with my arrayByPickingWithSelector: method, and my
>selectiveEnumerator class. Selective enumerators are initialized with a
>collection and a selector, and each call to -nextObject returns the next
>one that returned YES when sent the method called out by the selector.

This is exactly where HOM came from! I had an EnumFilter, EnumSelectFitler,
EnumRejectFilter, ReverseEnumFilter, ReverseEnumSelectFilter etc.

Then I had to do various cover methods to conveniently initialize the
various enum-filters with various numbers of arguments and various
combinations of static/dynamic arguments.

It just got out of hand after a while, so I started thinking what could
be a better way of specifying a messag to be sent along with various
arguments? Hmm, why not use just a plain message send? And then
freeze it using -forwardInvocation:? That's it.

>> -reject gather the objects that return NO (nil)

>Gee, I never needed this one ;-)

Yeah, not too often, but it does come in handy sometimes. That's
why I am loathe to implement more of the collection protocl just
for the sake of it.

>So, would it be correct to do the following to get all panels in an app?

>NSArray * myPanels =
> [[[NSApplication sharedInstance]
> windowList]
> collect]
> isKindOfClass:[NSPanel class]];

Yup.

Well, almost. There is a slight hickup with select/reject due to
(a) the definition of BOOL as char (b) the use of typed selectors
(c) the elimination of return-value widening in ANSI-C (and adoption
by Objective-C and (d) over-enthusiastic compilers. The end result
is that the compiler will mangle the return value of a message
declared as BOOL despite there being no need for it.

My current, ugly, workaround is to prefix '__' to messages used
with reject/select (these are later removed by the HOM-code) or
define/declare alternative methods with int return values.

I've also done a gcc patch.

>I think I like this.

Glad to hear that :-))

Peter Rasmussen

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to

I find Blocks an interesting way of writing methods in a more
compact way - which can (at times) also increase readability.

But a good dynamic collection library relieves their need
staying within ordinary messaging.


Helge> Besides that I still think that the advantage of blocks is that they
Helge> operate in the context of the callee and therefore can access state at
Helge> this side.

This is also the disadvantage of blocks.

The larger you start writing them - the more redundant you'll end up
getting your code - callee side code breaks code incapsulation.


This issue starts taking off, when you send blocks
out of their lexical scope for evaluation.


-- Peter


David Stes

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
Marcel Weiher wrote:
>
> Well, if you check the output of your translator, you will find
> that Objective-C methods turn out to be C functions.

Sigh.

This is very sad. So basically because the POC generates intermediate C
code it is not object-oriented ?

Blocks can reference the self variable, they can refer to instance and
class variables.

This discussion that Blocks are supposedly not object-oriented is
absurd.

Marcel Weiher

unread,
Aug 1, 2000, 3:00:00 AM8/1/00
to
David Stes <st...@pandora.be> writes:

>Marcel Weiher wrote:
>>
>> Well, if you check the output of your translator, you will find
>> that Objective-C methods turn out to be C functions.

>Sigh.

Yes, sigh indeed!

>This is very sad. So basically because the POC generates intermediate C
>code it is not object-oriented ?

Not in the least bit.

>Blocks can reference the self variable, they can refer to instance and
>class variables.

So?

>This discussion that Blocks are supposedly not object-oriented is
>absurd.

Yes. Try to read up on what an anonymous function is and compare
this with blocks.

Lee Willis

unread,
Aug 2, 2000, 3:00:00 AM8/2/00
to

"Marcel Weiher" <mar...@cs.tu-berlin.de> wrote in message
news:8m616u$m3n$1...@news.cs.tu-berlin.de...

> "Lee Willis" <lee-w...@home.com> writes:
>
> the original 'FP' notation before I encountered the use of blocks in
> Smalltalk's collection protocol. It deals with combinations of pure
> functions, thus allowing a much higher level of abstraction than
> dealing with individual elements.

I'm more than a little bit rusty when it comes to functional programming,
but isn't there a whole class of problems that FP can't deal with -- namely
those with state? e.g. I believe you can't do this with FP:

// Returns alternating true and false values
bool toggle(void) {
static bool state= false;
state= ! state;
return state;
}

Does the higher-order messaging you favor have the same limitations?

> >Does everyone remember the very first time you encountered the [] syntax
for
> >messaging? Every person I've known (including myself) disliked it at
first
> >glance. But quickly not only got used to it but became enamored with it.
I
> >think the block {} notation is the same thing.
>
> I have a question: do you think this is specifically *blocks* that you
> grew fond of, or mroe generally having some sort of reasonably
> convenient higher-order mechanism?

I like blocks, but that isn't to say that I wouldn't like some other higher
order
mechanism that fulfills the same need. I'm merely pointing out that at
least
some of the reluctance people are experiencing may be very temporary, and
that Blocks are much better than they appear at first blush.

Lee Willis

Marcel Weiher

unread,
Aug 2, 2000, 3:00:00 AM8/2/00
to
"Lee Willis" <lee-w...@home.com> writes:
>"Marcel Weiher" <mar...@cs.tu-berlin.de> wrote in message
>news:8m616u$m3n$1...@news.cs.tu-berlin.de...
>> "Lee Willis" <lee-w...@home.com> writes:
>>
>> the original 'FP' notation before I encountered the use of blocks in
>> Smalltalk's collection protocol. It deals with combinations of pure
>> functions, thus allowing a much higher level of abstraction than
>> dealing with individual elements.

>I'm more than a little bit rusty when it comes to functional programming,
>but isn't there a whole class of problems that FP can't deal with -- namely
>those with state? e.g. I believe you can't do this with FP:

The original 'FP' (the notation that John Backus introduced) was just
that, a notation, I think. I don't think you could even program in
it, and have never seen a compiler or interpreter.

As far as I remember my foundations of functional programming class,
you had to go to quite some lengths to even derive 'objects' (not in
the strict OO sense, but in the sense of data values) using this
mechanism.

> // Returns alternating true and false values
> bool toggle(void) {
> static bool state= false;
> state= ! state;
> return state;
> }

Well, modern functional languages also frown on this sort of thing,
and with some justification, but they do have a mechanism called
"monads" for dealing with state, which I know absolutely nothing
about except that it is widely used for I/O.

>Does the higher-order messaging you favor have the same limitations?

No. HOM is implemented as a library in Objective-C and has no way
of eliminating language features. OTOH, there is no additional
provision for state within a HOM-expression, because it is nothing
more than a nested Objective-C message-send:

[[slots do] setOriginal:nil];

>I like blocks, but that isn't to say that I wouldn't like some other higher
>order
>mechanism that fulfills the same need. I'm merely pointing out that at
>least
>some of the reluctance people are experiencing may be very temporary, and
>that Blocks are much better than they appear at first blush.

Yes, I think it is good to evaluate language constructs not on initial
reaction. All I am trying to point out is that Blocks are not as good
as they appear at first (or second :-) blush.

Smalltalk needed Blocks in exactly the shape they are in because it
doesn't have any other way of specifying control structures. For
#ifTrue:ifFalse: and friends, access to the enclosing scope and
the ability to have more than one message sent are essential, while
parallel stepping of arguments (there are no arguments to an #ifTrue:
block!) is not.

Objective-C does not have the same requirements because C has various
control mechanisms built-in.

Marcel

Helge Hess

unread,
Aug 2, 2000, 3:00:00 AM8/2/00
to Marcel Weiher
Marcel Weiher wrote:
> >I can't see why this shouldn't be possible ?! The frames can be archived
> >and the code can be added as well.
>
> You are going to dump machine-code from one running process to disk,
> unarchive it in a different process and except it to work?

No, I'm going to use the machine-code already on disk, eg in fat form,
and transfer that to the other machine (you aren't dumping Java bytecode
from the JVM too ...). Obviously that only works for platforms where
compiled code exists for.
One would need to have a code manager machinery, like the Java
class-loader which is aware of machine types and able to transfer code.
Certainly not impossible.

The nice thing about blocks in that context is that you can indeed
archive the callstack of the block and therefore restart execution on
the other machine !

> >That ObjC compiles the code
> >complicates the procedure but it certainly is possible.
>
> Go ahead! :-)

I have no need for sth like that, it's an interesting thing I have no
time for ;-)

> >BTW I do not agree that blocks are anonymous functions (though I first
> >thought that they are implemented that way in POC, which isn't true).
>
> I don't think I said they "are" anonymous functions. They *implement*
> the concept of anynoymous functions.

I would say they implement the concept of 'handle code as an object'.
How you use them is another thing. I can use blocks for many things,
including for
a) control structures
b) methods
c) anonymous code

You argue that ObjC already has control-structures. This is true, but
the nice thing about blocks is that you can create *new* control
structures. Indeed your HOM is basically doing the same thing in an
(IMHO) less convenient way.

b) is similiar. You can use blocks for methods, as ST does. Eg

block = {:arg| printf("%i", [arg intValue]); };
[myClass subclass:@"Blah" methods:@"doIt:", block, nil];
[otherClass subclass:@"Blub" methods:@"doIt:", block, nil];

Very interesting things can be done that way.
Currently I need to use static function to do things like that - IMHO
not very ObjC like

c) these are your functions. The (IMHO huge) difference is that the
callstack is preserved which opens a lot of interesting possibilities.

Probably there are some other interesting uses.

> >To me blocks are objects, since
> >they have the properties of an object, that is - they belong to a class,
> >they have behaviour and they own specific state. IMHO blocks are *very*
> >OO since they extend code to be objects as well.
>
> You are arguing on a different level, the implementation level, just
> like David. What I am saying is this: a message send vs. an anonymous
> chunk of arbitrary code. Which do you consider OO?

Both. Blocks itself are objects, not methods, and they are evaluated
using methods. I don't see any conflict with OO here. You can reuse
blocks by registering them as methods (or by some other means) if this
makes sense.

> >Besides that I still think that the advantage of blocks is that they

> >operate in the context of the callee and therefore can access state at

> >this side.
>
> This is one of the features I find much too powerful and unstructured.
> It's like having *hidden* global variables. Yuck.

Like with anything you need to be disciplined in programming. This is no
different with the concept of methods or classes (eg the problem of too
long methods).

I primarily see blocks as a tool for small sections of code which I
currently write as a static function, more specifically for comparison,
sorting or mapping operations. Writing a method for a 1-3 line block
seems completly weird to me especially given that the problem is of
local nature.
I see that some things can be done using your HOM but HOM is IMHO much
less convenient (and more difficult to understand) than code with
blocks.

> >Using HO messaging I would need to pass every state the block
> >needs to access using a parameter (the infamous 'context' object ...).
>
> Actually, that is a problem of blocks, not of HO-messages, because
> HO-messages are just messages, they already have these parameters.
> Having explicit parameters to methods vs. implicitly munging on
> state was generally considered a "good thing" last time I checked.

The state-munging is considered bad if done from a different point in
the source. I do not agree that it is a bad thing if the code using the
state is located at the same source code position.

I see no problem with
{
int sortOrdering = EOAscendingOrder;
array = [array sort:{:a:b|
if (sortOrdering) { id tmp = a; a = b; b = tmp; };
return [a compare:b]
}];
}

This can't be compared with global variables at all and is IMHO very
convenient.

If a block turns out to be reusable it still can be wrapped into a
method with parameters.

Helge

Marcel Weiher

unread,
Aug 2, 2000, 3:00:00 AM8/2/00
to
Helge Hess <helge...@skyrix.com> writes:

>The nice thing about blocks in that context is that you can indeed
>archive the callstack of the block and therefore restart execution on
>the other machine !

I think you haven't thought that one through, but I am glad to be
proven wrong!

>> >That ObjC compiles the code
>> >complicates the procedure but it certainly is possible.
>>
>> Go ahead! :-)

>I have no need for sth like that, it's an interesting thing I have no
>time for ;-)

I think you have even less time for it than you think, or rather,
it is a lot more complicated than you think.

>> I don't think I said they "are" anonymous functions. They *implement*
>> the concept of anynoymous functions.

>I would say they implement the concept of 'handle code as an object'.

Nope. Look at Smalltalk. A Method object is "code as object",
and even that is only "an object" in the very trivial fashion
that everything in Smalltalk is an object.

A Block, even in Smalltalk is an anonymous function. Yes, it
is also an object, but again only in the most trivial senses.

Strategy and Visitor patterns are much more an "objectification"
of "code" than blocks are, can be, or ever wanted to be.

>How you use them is another thing. I can use blocks for many things,
>including for
>a) control structures
>b) methods
>c) anonymous code

>You argue that ObjC already has control-structures.

Yes. This means that certain design considerations that were
necessary for blocks in Smalltalk just do not apply to
Objective-C, so taking the construct 1:1 is inapproriate.

> This is true, but
>the nice thing about blocks is that you can create *new* control
>structures.

Examples?

>Indeed your HOM is basically doing the same thing in an
>(IMHO) less convenient way.

No, it is focusing on the few things that are actually missing
and doing those in a much more convenient way.

>b) is similiar. You can use blocks for methods, as ST does. Eg

ST does *not* use blocks for methods. It uses Method objects
for methods. Blocks are a related construct for *anonymous*
code.

This may be where we have been miscommunicating. You've been
saying "block" and meaning "object wrapper for executable
code" while I have meant the specific block construct.

> block = {:arg| printf("%i", [arg intValue]); };
> [myClass subclass:@"Blah" methods:@"doIt:", block, nil];
> [otherClass subclass:@"Blub" methods:@"doIt:", block, nil];

> Very interesting things can be done that way.

The question is why you have to it an such a convoluted way.
Just define the method *normally*, then assign it to other
classes dynamically. I've been doing just that without
the need for blocks. Anyway, this could be made more
convenient by having an object representation of methods
and other runtime information. Blocks have nothing to
do with it.

> Currently I need to use static function to do things like that - IMHO
> not very ObjC like

Yes, and there is no need to do it that way even without any
object-wrapper for methods, but even with OO-wrappers for
methods you still don't have a need for blocks.

[snip]

>> You are arguing on a different level, the implementation level, just
>> like David. What I am saying is this: a message send vs. an anonymous
>> chunk of arbitrary code. Which do you consider OO?

>Both. Blocks itself are objects, not methods, and they are evaluated
>using methods. I don't see any conflict with OO here. You can reuse
>blocks by registering them as methods (or by some other means) if this
>makes sense.

You are missing my point, staying focused on low-level issues.

[access to caller context]

>Like with anything you need to be disciplined in programming. This is no
>different with the concept of methods or classes (eg the problem of too
>long methods).

This is very different, because it breaks encapsulation, one of
the fundamentals of OO.

>I primarily see blocks as a tool for small sections of code which I
>currently write as a static function, more specifically for comparison,
>sorting or mapping operations. Writing a method for a 1-3 line block
>seems completly weird to me especially given that the problem is of
>local nature.

After analyzing Smalltalk code for a while I found there are three
cases of blocks (exclusing blocks used for basic control structures):

1. single message sends: [ :each | each someMessage ]

This was the vast majority of cases, and is the case that
HOM handles much more conveniently.

2. large blocks

These should all be converted to methods. In fact, the
problem of these huge blocks inlined in methods when
they should be separated is one of my major gripes
with blocks.

The problem is that blocks strongly encourage the
inlining and strongly discourage out-lining.

3. medium sized blocks ( 2-3 message sends )

This is the case that HOM does not handle well,
and although one can (and I do) argue that
most if not all of these should be moved
outside of the method body as well and
given a proper name, the argument is not quite
as clear cut as with the other two cases.

>I see that some things can be done using your HOM but HOM is IMHO much
>less convenient (and more difficult to understand) than code with
>blocks.

It is much *more* convenient for simple blocks, and also easier
to read:

[[slots do] setOriginal:nil]
vs.
[slots do:{ :each | each setOriginal:nil].

Furthermore, it doesn't invert the message logic for message sends
where the receiver stays constant and an argument varies:

Say you have a database that you want to store an object on,
this gets written:

[database storeObject:myObject];

The program logic reads directly from the statements as written.
If you want to store a whole bunc of objects by iterating over
them using blocks, the entire expression gets turned upside
down:

[myObjects do:{:each | databases storeObject each}].

The expression now looks completely different and only if you
analyze it carefully can you figure out what is going on,
because the initial receiver of the message expression as
written is not the actual receiver of the messages that
are intended!

With HOM, this is not a problem because the structure of the
original message expression remains the same, just getting
augmented slightly:

[[database do] storeObject:[myObjects each]]

Also, there are expressions that blocks just cannot handle at
all without introducing additional top-level iteration methods:

[[myPrefixes collect] stringByAppendingString:[mySuffixes each]]

You cannot handle this with the -collect: method unless you do
your own iteration, which is not the point of the exercise.

[accessing enclsing state]

>The state-munging is considered bad if done from a different point in
>the source. I do not agree that it is a bad thing if the code using the
>state is located at the same source code position.

>I see no problem with
> {
> int sortOrdering = EOAscendingOrder;
> array = [array sort:{:a:b|
> if (sortOrdering) { id tmp = a; a = b; b = tmp; };
> return [a compare:b]
> }];
> }

Yes, this seems reasonable. However, the problem I have with this
is that I've seen pretty much this code at least twice from you
in, it seems, different contexts (that is just an impression).

My experience with blocks is that it leads to lots of duplicated
code lying around in little snippets like the one you show here.

>If a block turns out to be reusable it still can be wrapped into a
>method with parameters.

Except that by that time it usually has been duplicated many, many
times. Extracting it once and then reusing it may seem a little
less convenient, but typically pays off.

Peter Rasmussen

unread,
Aug 2, 2000, 3:00:00 AM8/2/00
to

Saving multiple objects;

Blocks: [myObjects do:{:each | databases storeObject each}].

HOM: [[database do] storeObject:[myObjects each]]


Shortest with straight messaging:

[database storeObjects: myObjects];

after adding one *general purpose* message on the database

// ------------

>I see no problem with
> {
> int sortOrdering = EOAscendingOrder;
> array = [array sort:{:a:b|
> if (sortOrdering) { id tmp = a; a = b; b = tmp; };
> return [a compare:b]
> }];
> }

-[NSArray sortEOAscending];
-[NSArray sortEODescending];

Can't be shorter than with straight messaging after you have implemented
these two again *general purpose* methods.


- Peter


Marcel Weiher

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to
Peter Rasmussen <ras...@interactive-technology.NOSPAM.com> writes:

>Saving multiple objects;

>Blocks: [myObjects do:{:each | databases storeObject each}].

>HOM: [[database do] storeObject:[myObjects each]]


>Shortest with straight messaging:
>
> [database storeObjects: myObjects];

Exactly! (I was hoping someone would bring this up)

>after adding one *general purpose* message on the database

Yes, this is why the 'reverse' form of HOM is not used that often,
though it does happen, simply because sometimes it just doesn't
make sense to add the general purpose method, for example if it's
only used once.

>>I see no problem with
>> {
>> int sortOrdering = EOAscendingOrder;
>> array = [array sort:{:a:b|
>> if (sortOrdering) { id tmp = a; a = b; b = tmp; };
>> return [a compare:b]
>> }];
>> }

>-[NSArray sortEOAscending];
>-[NSArray sortEODescending];

>Can't be shorter than with straight messaging after you have implemented
>these two again *general purpose* methods.

Yes, this is exactly the problem I have seen with blocks in Smalltalk.
Putting functionality inline is so tempting that you don't bother
to create generalized methods, leading to far less understandable
code fragments and important functionality splattered anonymously over
the system.

The problem with blocks as the sole or primary mechanism for iteration
(this applies to Smalltalk) is that they provide a strong disincentive
against breaking that common code into a separate method. Why is this
so? The reason is that you're going to have to use a block anyway,
which has quite a bit of syntactic overhead, so adding the method-body
inline to that block is only marginally more work.

One of the ideas of HOM is to make the most common iteration patterns
(send a single message) a lot less cumbersome than with blocks, so
there is some incentive to break out that code into a separate method.

Helge Hess

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to Peter Rasmussen
Peter Rasmussen wrote:
>
> Saving multiple objects;
>
> Blocks: [myObjects do:{:each | databases storeObject each}].
>
> HOM: [[database do] storeObject:[myObjects each]]
>
> Shortest with straight messaging:
>
> [database storeObjects: myObjects];
>
> after adding one *general purpose* message on the database

This was also my first thought ;-) It's not only the shortest, but also
the most convenient, IMHO.

> // ------------


>
> >I see no problem with
> > {
> > int sortOrdering = EOAscendingOrder;
> > array = [array sort:{:a:b|
> > if (sortOrdering) { id tmp = a; a = b; b = tmp; };
> > return [a compare:b]
> > }];
> > }
>

> -[NSArray sortEOAscending];
> -[NSArray sortEODescending];
>
> Can't be shorter than with straight messaging after you have implemented
> these two again *general purpose* methods.

The problem is, that the above is an over-simplification. In reality you
need to check for nil/null values, for special states like
upper/lowercase and so on. That is why there is an -sortUsingFunction:
method.
Writing a method for each ordering block is IMHO very bad style, since
a) the class will be heavily polluted with methods, which b) are only
used in a local context and therefore belong to that source position.

BTW: the point in the above was that the ordering spec comes out of the
block environment. In reality you would probably make a
-sortedArrayUsingOrdering: or sth like that which is a problem if you
have more state than a single variable (too much parameters).

I still think that blocks are a very valuable addition (if implemented
correctly). I see that the opinions differ but after all nobody is
forced to use blocks. So if possible, I would vote for adding them to
ObjC.

Helge

Helge Hess

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to Marcel Weiher
Marcel Weiher wrote:
> >The nice thing about blocks in that context is that you can indeed
> >archive the callstack of the block and therefore restart execution on
> >the other machine !
>
> I think you haven't thought that one through, but I am glad to be
> proven wrong!

I haven't, but can see a problem either. All call-state the block can
access is stored in the heap as frame objects. I can't see why the
frames can't be archived/unarchived as usual. Of course all objects
involved must support coding.

> >> >That ObjC compiles the code
> >> >complicates the procedure but it certainly is possible.

> I think you have even less time for it than you think, or rather,
> it is a lot more complicated than you think.

If you think so ...

> [access to caller context]
>
> >Like with anything you need to be disciplined in programming. This is no
> >different with the concept of methods or classes (eg the problem of too
> >long methods).
>
> This is very different, because it breaks encapsulation, one of
> the fundamentals of OO.

I can't see how blocks break encapsulation of objects ?! Like any plain
C compound statement a block can access it's context. Local variables
are encapsulated by scoping, which applies as usual.

> After analyzing Smalltalk code for a while I found there are three
> cases of blocks (exclusing blocks used for basic control structures):

I hope you understand that I do not care a lot about your 'analyzation'.
This is obviously style and application dependend in a huge way and your
sample set may have been bad.

> >I see that some things can be done using your HOM but HOM is IMHO much
> >less convenient (and more difficult to understand) than code with
> >blocks.
>
> It is much *more* convenient for simple blocks, and also easier
> to read:
>
> [[slots do] setOriginal:nil]
> vs.
> [slots do:{ :each | each setOriginal:nil].

The difficult(=inconvenient) thing to understand is the magic behind
'do' in HOM. Everyone easily understands what a block is, since one
knows compound-statements. It's a straightforward addition, IMHO.

To grasp what 'do' in HOM does is definitly *not* easy for someone who
has not thought a lot about NSInvocation objects. This probably doesn't
apply to you ...

> Furthermore, it doesn't invert the message logic for message sends
> where the receiver stays constant and an argument varies:

The problem is the 'receiver' which is a piece of magic with HOM. In
'[each setOriginal:nil]' the receiver is obvious.

> Say you have a database that you want to store an object on,
> this gets written:
>
> [database storeObject:myObject];
>
> The program logic reads directly from the statements as written.
> If you want to store a whole bunc of objects by iterating over
> them using blocks, the entire expression gets turned upside
> down:
>
> [myObjects do:{:each | databases storeObject each}].
>
> The expression now looks completely different and only if you
> analyze it carefully can you figure out what is going on,
> because the initial receiver of the message expression as
> written is not the actual receiver of the messages that
> are intended!

I do not agree. Indeed you are using Smalltalk syntax, which is less
obvious here (IMHO). That:

[myObjects do:{:each | [database storeObject:each]}];

is very easy to understand, IMHO. But you are always staying at the
single-message examples which is the only case handled by HOM. In
reality you will have sth like that:

[myObject do:{:each |
if ([each isPersistent] || [each isReachable])
[database storeObject:each]}];

Of course you will say that you have analyzed that and such specialized
sections never occur in practice, but I just do not agree.

> With HOM, this is not a problem because the structure of the
> original message expression remains the same, just getting
> augmented slightly:
>
> [[database do] storeObject:[myObjects each]]

IMHO this is very difficult to understand because of magic. Nothing is
obvious in that statement. Even I ;-)) have to think a minute to
understand how this is accomplished.
Ever tried to explain HOM to a beginner ? How do you explain what the
receiver of 'storeObject:' is, and what the argument ?

> >I see no problem with
> > {
> > int sortOrdering = EOAscendingOrder;
> > array = [array sort:{:a:b|
> > if (sortOrdering) { id tmp = a; a = b; b = tmp; };
> > return [a compare:b]
> > }];
> > }
>
> Yes, this seems reasonable. However, the problem I have with this
> is that I've seen pretty much this code at least twice from you
> in, it seems, different contexts (that is just an impression).

I would argue that having duplicates of 3-lines sections is indeed not
that bad. Having to document and maintain a method for these piece is
going to turn out more difficult. A 3-line section is self-documenting.

I agree that there is the danger that people misuse blocks, but this is
no different with any other construct.

You classified blocks into three categories: a) single-msg-send, b)
small blocks, c) large blocks. HOM only covers a) and c), and c) only if
the code is non-local. Blocks cover all uses and are therefore the
better concept, IMHO.

Greetings
Helge

Marcel Weiher

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to
Helge Hess <helge...@skyrix.com> writes:

>I still think that blocks are a very valuable addition (if implemented
>correctly). I see that the opinions differ but after all nobody is
>forced to use blocks. So if possible, I would vote for adding them to
>ObjC.

While I agree that blocks add some benefit, I don't think they pass
a cost/benefit analysis. For Smalltalk blocks provide three
benefits:

1. control structures -> we have them from C
2. collection iteration -> HOM does a better job without the
need for a language modification
3. inline specification -> benificial in some circumstances
of sort-blocks etc. harmful in others

The epsilon of additional benefit is just too small to justify
such a significant addition to the languasge.

Really, creating a true Smalltalk sitting on top the Objective-C
runtime and class-libraries is probably less work.

Marcel Weiher

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to
Helge Hess <helge...@skyrix.com> writes:

>I hope you understand that I do not care a lot about your 'analyzation'.
>This is obviously style and application dependend in a huge way and your
>sample set may have been bad.

The sample is the Squeak image. It is pretty damn big and contains
lots of code from many excellent Smalltalkers. Come up with something
better before dismissing it!

>> It is much *more* convenient for simple blocks, and also easier
>> to read:
>>
>> [[slots do] setOriginal:nil]
>> vs.
>> [slots do:{ :each | each setOriginal:nil].

>The difficult(=inconvenient) thing to understand is the magic behind
>'do' in HOM. Everyone easily understands what a block is, since one
>knows compound-statements. It's a straightforward addition, IMHO.

Sorry, I don't see this at all, quite the contrary. The "magic"
behind 'do' is very easy to explain: send the message not just
to a single object, but to every object you contain.

The explanation of how exactly blocks work is much more complicated,
because you have to go into details about how variables are shared,
how stuff is executed etc.

>To grasp what 'do' in HOM does is definitly *not* easy for someone who
>has not thought a lot about NSInvocation objects. This probably doesn't
>apply to you ...

It is so patently easy that any child can understand it. Take a message,
and write it on a piece of paper. Pass it to a single person. That's
normal message passing. Take the same piece of paper. Hand it to
a group of people. What's difficult about that?

Try to explain closures to someone. They get evaluated at some later
time by completely different code, but sortof carry some of the
other context around with them as well. Yikes!

Then there are the specifics of how the context-sharing is done.
This tends to be quite non-obvious, tends to stump the experts
and is one area where even the highest quality Smalltalk
implementations have subtle bugs and/or disagreements.

It is not easy!

>> Furthermore, it doesn't invert the message logic for message sends
>> where the receiver stays constant and an argument varies:

>The problem is the 'receiver' which is a piece of magic with HOM. In
>'[each setOriginal:nil]' the receiver is obvious.

It might be easer if I hadn't chosen the traditional ST names.
'foreach' might make it more clear, but it makes it more
difficult to distinguish between the different uses.

Anyway, where 'each' comes from is no more obvious, the user
has to *learn* that -do: evaluates the block with all of
its contents, binding 'each' to every single one of its
members. Same with -do, you also have to learn what it
does.

[example snipped]

>I do not agree. Indeed you are using Smalltalk syntax, which is less
>obvious here (IMHO). That:

> [myObjects do:{:each | [database storeObject:each]}];

>is very easy to understand, IMHO.

Yes, IYHO. The problem you are refusing to see is that the
actual recipient of the message expression, 'database' is
hidden deep inside the expression, surrounded by a lot of
gunk that is only needed to make the expression work, that
doesn't actually contribute.

>But you are always staying at the
>single-message examples which is the only case handled by HOM.

Yes, because these are the most common, and...

>In
>reality you will have sth like that:

> [myObject do:{:each |
> if ([each isPersistent] || [each isReachable])
> [database storeObject:each]}];

at this point, I would want a separate method that tells me
what this code is supposed to do (see Kent Beck's Smalltalk
Best Practive Patterns, the part about Intention Revealing
Message Names).

>Of course you will say that you have analyzed that and such specialized
>sections never occur in practice, but I just do not agree.

I *never* said that they do not occur in practice. Quite the contrary,
I've always stated quite clearly that it is exactly these types of
mid-size blocks that HOM doesn't handle well.

However, HOM definitely handles small and large size 'blocks' better
than an actual block mechanism, and one can argue that even for
mid-size blocks such as your example, a separate method with an
intention-revealing name is better. One can also argue against it,
so we can regard this one as a toss-up.

So of the three cases you have 2 that are clearly better, and one
that is a toss up. Add to that the fact that Blocks are a language
extension and HOM is not, and the result is pretty clear: the
beneits of blocks in the presence of HOM are so tiny that they don't
justify the considerable expense of a language addition.

>> With HOM, this is not a problem because the structure of the
>> original message expression remains the same, just getting
>> augmented slightly:
>>
>> [[database do] storeObject:[myObjects each]]

>IMHO this is very difficult to understand because of magic. Nothing is
>obvious in that statement. Even I ;-)) have to think a minute to
>understand how this is accomplished.

Therein lies the problem: you are trying to understand the construct
through implementation, instead of coceptually. Conceptually,
it is *very* simple.

>Ever tried to explain HOM to a beginner ? How do you explain what the
>receiver of 'storeObject:' is, and what the argument ?

Yes, frequently. It is much easier to explain than most other
prog-lang constructs, if you've explained message passing
before. Take message. Send once. Send many. If you've
seen a SPAM mail or a CC list, you understand HOM.

[example snipped]

>I would argue that having duplicates of 3-lines sections is indeed not
>that bad.

Yes, you would. But you are wrong, duplicates of 3-line sections are
extremely bad once you start maintaining code. I just went through
a several hour session refactoring some of my employees' code. The
biggest problem were the duplicates of 3-4 line sections, because
they were all over the place and difficult to find (can't easily
grep for them). Furthermore, then you start to see variations of
those three lines, and you never know wether this particular
variation is intentional or just reflects the fact that someone
forgot to update this particular 3 line section.

>Having to document and maintain a method for these piece is
>going to turn out more difficult. A 3-line section is self-documenting.

1. It would be self-documenting if it were a method with an
intention revealing name.
The way it is presented, it took me a while to figure out.
2. Unless you have weird documenting standards, documenting
the inlined code is going to be more work because with
the separate method, you have the chance of giving the
method a good name that makes the code actually self-
documenting.

>I agree that there is the danger that people misuse blocks, but this is
>no different with any other construct.

Yes, so you have to weight the costs+dangers vs. the benefits.

>You classified blocks into three categories: a) single-msg-send, b)
>small blocks, c) large blocks. HOM only covers a) and c), and c) only if
>the code is non-local. Blocks cover all uses and are therefore the
>better concept, IMHO.

That is an 'interesting' way of putting it. All the cases are handled
by both methods (turing complete and all that) a+c are handled better
by HOM, b is handled better by blocks, making it 2:1 *for* HOM, and
that is assuming I completely buy your arguments. I'd say that
b is only a very slight advantage, close to a toss-up, so it's more
like 2.3:.7 for HOM.

Considering HOM does *not* require a language addition and blocks
*do* require a language addition, makes the whol thing a no-contest
sort of proposition! Even if it were 2:1 for blocks (as in your
strange way of counting above), I still wouldn't think that such
marginal benefit would justify a language addition.

And yes, if HOM required a language addition, I would also be
much more skeptical.

Think cost/benefit.

David Stes

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to
Marcel Weiher wrote:
>
> Peter Rasmussen <ras...@interactive-technology.NOSPAM.com> writes:
>
> >Saving multiple objects;
>
> >Blocks: [myObjects do:{:each | databases storeObject each}].
>
> >HOM: [[database do] storeObject:[myObjects each]]
>
> >Shortest with straight messaging:
> >
> > [database storeObjects: myObjects];
>
> Exactly! (I was hoping someone would bring this up)

That someone happens to be another apple fan.

So, "by coincidence" another apple fan brings up an "argument" against
Blocks (Blocks happen to be unsupported in apple's compiler).

Anyway, I can do shorter than Peter Rasmussen's syntax.

store(database,myObjects);

Wow, now I really have an argument against Objective-C message syntax.

Stephen Peters

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to
David Stes <st...@pandora.be> writes:

> Marcel Weiher wrote:
> >
> > Peter Rasmussen <ras...@interactive-technology.NOSPAM.com> writes:
> >
> > >Shortest with straight messaging:
> > >
> > > [database storeObjects: myObjects];
> >
> > Exactly! (I was hoping someone would bring this up)
>
> That someone happens to be another apple fan.
>
> So, "by coincidence" another apple fan brings up an "argument" against
> Blocks (Blocks happen to be unsupported in apple's compiler).

Oh, for gods sake. Will you please grow up and stop these damned
paranoid rants. People can dislike blocks without being a member of a
conspiracy.

(As an aside, how the hell are we ever going to unify the Objective-C
compilers if one of the principal compiler architects can't listen to
criticisms with an open mind?)

--
Stephen L. Peters por...@ai.mit.edu
PGP fingerprint: A1BF 5A81 03E7 47CE 71E0 3BD4 8DA6 9268 5BB6 4BBE
"Poodle: The other white meat." -- Sherman, Sherman's Lagoon

Peter Rasmussen

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to

Marcel> It might be easer if I hadn't chosen the traditional ST names.
Marcel> 'foreach' might make it more clear, but it makes it more difficult
Marcel> to distinguish between the different uses.
Marcel>
Marcel> Anyway, where 'each' comes from is no more obvious, the user has to
Marcel> *learn* that -do: evaluates the block with all of its contents,
Marcel> binding 'each' to every single one of its members. Same with -do,
Marcel> you also have to learn what it does.

[myObjects do:{:each | [database storeObject:each]}];

[[database do] storeObject:[myObjects each]]


While I accept -do: of HOM over makeObjectsPerformSelector:

I have problems with -each not being anywhere intuitive
under the traditional paradigm of messaging.

A few more *generic methods* might elimimate the need for 'each' in HOM.
like ...

[NSEnumerator perform:SEL on:array1 with:array2];


Helge> However, HOM definitely handles small and large size 'blocks' better
Helge> than an actual block mechanism, and one can argue that even for
Helge> mid-size blocks such as your example, a separate method with an
Helge> intention-revealing name is better. One can also argue against it,
Helge> so we can regard this one as a toss-up.

Helge > [myObject do:{:each |
Helge > if ([each isPersistent] || [each isReachable])
Helge > [database storeObject:each]}];


How about this all one selector HOM structure ...

[[[[[[myObjects collect] isPersistent]
collect] isReachable]
do] storeOn: database]


-- Peter

Marcel Weiher

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to
Peter Rasmussen <ras...@interactive-technology.NOSPAM.com> writes:

> [myObjects do:{:each | [database storeObject:each]}];

> [[database do] storeObject:[myObjects each]]


>While I accept -do: of HOM over makeObjectsPerformSelector:

>I have problems with -each not being anywhere intuitive
>under the traditional paradigm of messaging.

Yes, I am not really happy with 'each' myself. However, I haven't
come up with anything better yet. 'foreach' might be a better
name to indicate that you don't mean to pass the object but
its contents. (By the way, -each is just a cover for
-objectEnumerator)

Another option might be to simply regard arrays as iterable,
but I rejected that because arrays make reasonable non-
iterated arguments. It might be itneresting to try
that variant, however.

>A few more *generic methods* might elimimate the need for 'each' in HOM.
>like ...

> [NSEnumerator perform:SEL on:array1 with:array2];

How does that distinguish between a variable and a constant parameter?

>Helge> However, HOM definitely handles small and large size 'blocks' better
>Helge> than an actual block mechanism, and one can argue that even for
>Helge> mid-size blocks such as your example, a separate method with an
>Helge> intention-revealing name is better. One can also argue against it,
>Helge> so we can regard this one as a toss-up.

>Helge > [myObject do:{:each |
>Helge > if ([each isPersistent] || [each isReachable])
>Helge > [database storeObject:each]}];


>How about this all one selector HOM structure ...

> [[[[[[myObjects collect] isPersistent]
> collect] isReachable]
> do] storeOn: database]

Actually, that would be:

[[database do] storeOn:[[[[[myObjects select] isPersistent] select] isReachable] each]]

but (as Helge is sure to point out) this only works for the AND case, not for OR.

I was working on ways to get selects to work, but nothing conclusive yet.

The basic way is to build up expression, which is doable with this technique.
The interesting part about that is that the expressions are actually
structured, so whereas an array would just execute the expression, a
database could in fact take the expression apart and convert it into
an SQL query for the DB. I can't help myself, but that would be *really*
cool. Alas, also somewhat difficult.

Lee Willis

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to

"Marcel Weiher" <mar...@cs.tu-berlin.de> wrote in message
news:8m68ap$oni$1...@news.cs.tu-berlin.de...

> "John C. Randolph" <j...@idiom.com> writes:

[talking about Higher-Order Messaging (HOM)]

> Well, almost. There is a slight hickup with select/reject due to
> (a) the definition of BOOL as char (b) the use of typed selectors
> (c) the elimination of return-value widening in ANSI-C (and adoption
> by Objective-C and (d) over-enthusiastic compilers. The end result
> is that the compiler will mangle the return value of a message
> declared as BOOL despite there being no need for it.
>
> My current, ugly, workaround is to prefix '__' to messages used
> with reject/select (these are later removed by the HOM-code) or
> define/declare alternative methods with int return values.
>
> I've also done a gcc patch.

So HOM does require a change to the Obj-C compiler?

Earlier in this thread, you wrote:

>No. HOM is implemented as a library in Objective-C and has no way
>of eliminating language features. OTOH, there is no additional
>provision for state within a HOM-expression, because it is nothing
>more than a nested Objective-C message-send:

Which gave me the impression that HOM worked w/o modifying the compiler.


Lee Willis

Peter Rasmussen

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to

Marcel> Yes, I am not really happy with 'each' myself. However, I haven't
Marcel> come up with anything better yet. 'foreach' might be a better name
Marcel> to indicate that you don't mean to pass the object but its contents.
Marcel> (By the way, -each is just a cover for -objectEnumerator)

Peter> [NSEnumerator perform:SEL on:array1 with:array2];

Marcel> How does that distinguish between a variable and a constant parameter?

How about these three general purpose methods:

[array do:@selector(selector) withObject:object]
[object do:@selector(selector) overArray:myArguments];
[array do:@selector(selector) overArray:array2];

Marcel> Actually, that would be:
Marcel>
Marcel> [[database do] storeOn:[[[[[myObjects select] isPersistent]
Marcel> select] isReachable] each]]
Marcel>
Marcel> but (as Helge is sure to point out) this only works for the AND
Marcel> case, not for OR. I was working on ways to get selects to work,
Marcel> but nothing conclusive yet.

You just need some Array operations like OR, AND, EXOR

[[[myObjects select] isPersistent] and: [[myObjects select] isReachable]]
[[[myObjects select] isPersistent] or: [[myObjects select] isReachable]]


Marcel> The basic way is to build up expression, which is doable with this
Marcel> technique. The interesting part about that is that the expressions
Marcel> are actually structured, so whereas an array would just execute the
Marcel> expression, a database could in fact take the expression apart and
Marcel> convert it into an SQL query for the DB. I can't help myself, but
Marcel> that would be *really* cool. Alas, also somewhat difficult.

IMHO this is a case for passing blocks (working on some interfaces) ...
or for an interpreter like it's done in SQL.


-- Peter

Marcel Weiher

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to
Peter Rasmussen <ras...@interactive-technology.NOSPAM.com> writes:

>Peter> [NSEnumerator perform:SEL on:array1 with:array2];
>Marcel> How does that distinguish between a variable and a constant parameter?

>How about these three general purpose methods:

> [array do:@selector(selector) withObject:object]
> [object do:@selector(selector) overArray:myArguments];
> [array do:@selector(selector) overArray:array2];

Well, that is exactly one argument. Now expand to 3-4 arguments,
with each combination and you've got an exponential growth in
the number of methods. Then multiply that by each of the operations
you want ( -do, -collect, -select, -reject, -fold, others...)

What you are proposing is the solution I had before I came up with
HOM. The problems I had with it were the following: long-winded
and indirect way of specifying a message send that completely
destroys the advantages of the keyword syntax:

[array selector:object]
vs.
[array performSelector:@selector(selector) with:object];

Then the method explosion I've already mentioned, and also the
fact that these expressions are complicated enough by themselves
that you're not going to be able to nesst them well if at all.

A very practicaly consideration was that you can't (to my
knowledge) specify SELs in WebScript, though that point
is a little moot right now. HOM works just fine from
bridged environments, which neither this solution nor
blocks do (I've tried it with WebScript, FScript, Squeak
and my own little Smalltalk spike)

>Marcel> Actually, that would be:
>Marcel>
>Marcel> [[database do] storeOn:[[[[[myObjects select] isPersistent]
>Marcel> select] isReachable] each]]
>Marcel>
>Marcel> but (as Helge is sure to point out) this only works for the AND
>Marcel> case, not for OR. I was working on ways to get selects to work,
>Marcel> but nothing conclusive yet.

>You just need some Array operations like OR, AND, EXOR

>[[[myObjects select] isPersistent] and: [[myObjects select] isReachable]]
>[[[myObjects select] isPersistent] or: [[myObjects select] isReachable]]

Yes, in principle. However, that doesn't jive with the way the operations
work now, because the selects are evaluated immediately. I had a different
(long) form that went something like this:

[[[myObjects forall] isPersistent] or:[[myObjects forall] isReachable] select];

The trick is to keep the expression "open" while you're accumulating stuff.

Oh wait, now I see! You just want the operations to work on the resulting arrays.
Hmm, yes, that would probably work.

>Marcel> The basic way is to build up expression, which is doable with this
>Marcel> technique. The interesting part about that is that the expressions
>Marcel> are actually structured, so whereas an array would just execute the
>Marcel> expression, a database could in fact take the expression apart and
>Marcel> convert it into an SQL query for the DB. I can't help myself, but
>Marcel> that would be *really* cool. Alas, also somewhat difficult.

>IMHO this is a case for passing blocks (working on some interfaces) ...

The problem is that the block does not contain a structured expression,
but just some code that can be executed (and that is pretty much all
you can do with the contents of the block). So you can't get at
the meaning of the expression, thus making it unlikely that you'll
be able to interpret the thing.

>or for an interpreter like it's done in SQL.

Well, then you have yet another interpreter for yet another language,
just like EOF, for example. The typical problem is that these
mechanisms will usually be built only for DB-access tools, so you
have completely different mechanisms for doing selects. With arrays
and other collections, you use blocks or HOM, and then with the DB
you use this separate SQL that is paassed in strings parsed at runtime
(or worse, embedded SQL)

Wouldn't it be much cooler if the same (higher order) mechanism
that you use for arrays etc. could automagically be used with a
database to produce an optimized fetch?

Maybe that's just me, but I like to use a few tools uniformly,
if at all possible.

That being said, I have to admit I currently don't know how to
build it, but then again I haven't put too much thought into
it. Maybe someone here has a good idea.

Marcel Weiher

unread,
Aug 3, 2000, 3:00:00 AM8/3/00
to
"Lee Willis" <lee-w...@home.com> writes:

>So HOM does require a change to the Obj-C compiler?

No it doesn't require the change. There are various
ways of dealing with the issue.

>Earlier in this thread, you wrote:

>>No. HOM is implemented as a library in Objective-C and has no way
>>of eliminating language features. OTOH, there is no additional
>>provision for state within a HOM-expression, because it is nothing
>>more than a nested Objective-C message-send:

>Which gave me the impression that HOM worked w/o modifying the compiler.

Which is true: I've been using it for quite some time without the
compiler patch. The compiler patch would remove a little ugliness
that is a result of a combination of circumstances beyond my
control, but the whole HOM idea is a *pragmatic* one (just like
Objective-C, if I may add...).

Peter Rasmussen

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to

>How about these three general purpose methods:

> [array do:@selector(selector) withObject:object]
> [object do:@selector(selector) overArray:myArguments];
> [array do:@selector(selector) overArray:array2];

Marcel> Well, that is exactly one argument. Now expand to 3-4 arguments,
Marcel> with each combination and you've got an exponential growth in the
Marcel> number of methods. Then multiply that by each of the operations
Marcel> you want ( -do, -collect, -select, -reject, -fold, others...)
Marcel>
Marcel> What you are proposing is the solution I had before I came up with
Marcel> HOM. The problems I had with it were the following: long-winded
Marcel> and indirect way of specifying a message send that completely destroys
Marcel> the advantages of the keyword syntax:

I have a number of these too ...

But I wouldn't call it a code explosion, cause each of them are just a few
lines of code - so that makes you equal already by the *second* usage.


Marcel> [array selector:object] vs.
Marcel> vs. [array performSelector:@selector(selector) with:object];

vs. [array perform:SEL(storeOn:) with:object1 with:object2];


Marcel> A very practicaly consideration was that you can't (to my knowledge)
Marcel> specify SELs in WebScript, though that point is a little moot right
Marcel> now. HOM works just fine from bridged environments, which neither
Marcel> this solution nor blocks do (I've tried it with WebScript, FScript,
Marcel> Squeak and my own little Smalltalk spike)

How about wrapping SEL's into objects then ...
Would work equally fine in bridged environments

You could do that in the SEL() macro


Peter> You just need some Array operations like OR, AND, EXOR

Peter> [[[myObjects select] isPersistent] and: [[myObjects select] isReachable]]
Peter> [[[myObjects select] isPersistent] or: [[myObjects select] isReachable]]

Marcel> Yes, in principle. However, that doesn't jive with the way the
Marcel> operations work now, because the selects are evaluated immediately.
Marcel> I had a different (long) form that went something like this:
Marcel>
Marcel> [[[myObjects forall] isPersistent] or:[[myObjects forall]
Marcel> isReachable] select];
Marcel>
Marcel> The trick is to keep the expression "open" while you're accumulating
Marcel> stuff.
Marcel>
Marcel> Oh wait, now I see! You just want the operations to work on the
Marcel> resulting arrays. Hmm, yes, that would probably work.

Yes my intension was to filter the objects first ...
and then store those needed

What are you doing in your HOM code ...
building Qualifier structures for a generic select ???

-- Peter


Lee Willis

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to
"Marcel Weiher" <mar...@cs.tu-berlin.de> wrote in message
news:8mcmac$514$1...@news.cs.tu-berlin.de...

> "Lee Willis" <lee-w...@home.com> writes:
>
> >So HOM does require a change to the Obj-C compiler?
>
> No [snip]

> Which is true: I've been using it for quite some time without the
> compiler patch. The compiler patch would remove a little ugliness
> that is a result of a combination of circumstances beyond my
> control, but the whole HOM idea is a *pragmatic* one (just like
> Objective-C, if I may add...).

I like HOM. I think it's a great idea. The question wasn't meant to be a
dig. But within the context of this discussion, which is "HOM compared and
contrasted with Blocks", I want to keep track of what's already supported in
existing ObjC compilers, and what's non-standard.

Lee Willis


Marcel Weiher

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to
Peter Rasmussen <ras...@interactive-technology.NOSPAM.com> writes:

>I have a number of these too ...

>But I wouldn't call it a code explosion, cause each of them are just a few
>lines of code - so that makes you equal already by the *second* usage.

Sure, it is better than the alternative, explicit looping, which is
why I started it. However, once you cover the cases it gets annoying
writing structurally identical code. Hmm, maybe I am just more
annoyed by writing duplicated code than others...

>Marcel> [array selector:object] vs.
>Marcel> vs. [array performSelector:@selector(selector) with:object];

>vs. [array perform:SEL(storeOn:) with:object1 with:object2];

Still not good, IMHO. You've still completely eliminated the advantages
of keyword syntax etc.

>How about wrapping SEL's into objects then ...
>Would work equally fine in bridged environments

>You could do that in the SEL() macro

Yes, that's also an option.

[select examples snipped]

>Yes my intension was to filter the objects first ...
>and then store those needed

>What are you doing in your HOM code ...
>building Qualifier structures for a generic select ???

Not 'doing', but yes, that's another one of the ideas:
get as close to a generic SQL select as you can get
(and stop once you've covered a good fraction of cases)

I've experimented with it, but never took it far, partly
because I don't really do that much DB programming and
have this thing about only writing code I actually need.

Another reason is that my first expolarations showed it
to not be trivially easy, though it did show some possible
solutions.

John C. Randolph

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to

Stephen Peters wrote:

> Oh, for gods sake. Will you please grow up and stop these damned
> paranoid rants. People can dislike blocks without being a member of a
> conspiracy.
>
> (As an aside, how the hell are we ever going to unify the Objective-C
> compilers if one of the principal compiler architects can't listen to
> criticisms with an open mind?)

David isn't a "principal compiler architect." He is the author of an
irrelevant distraction. There is only one Objective-C compiler that
matters (GCC) and only two Obj-C runtimes that matter (the Darwin Obj-C
runtime, and the Gnu Obj-C runtime.)

There's no more need to "unify" Objective-C and the POC, than there is
to unify Objective-C and TOM. (Considerably less, in fact.)

-jcr

Marcel Weiher

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to
"Lee Willis" <lee-w...@home.com> writes:

>I like HOM. I think it's a great idea.

Great to hear that. :-)

> The question wasn't meant to be a
>dig. But within the context of this discussion, which is "HOM compared and
>contrasted with Blocks", I want to keep track of what's already supported in
>existing ObjC compilers, and what's non-standard.

And that's a good thing! All I wanted to point out was that it does
work with current compilers. Note also that this issue 'only' affects
-select and -reject.

Another limitation of the current implementation is that I haven't
bothered to deal with structures etc. simply because so far I
haven't had a need to do that. The current implementation also
has a hard limit of somewhere around 10 parameters; this is also
something I haven't bumped into yet.

However, it should be easy to come up with better implementations.

David Stes

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to
"John C. Randolph" wrote:
>
> David isn't a "principal compiler architect." He is the author of an
> irrelevant distraction. There is only one Objective-C compiler that
> matters (GCC) and only two Obj-C runtimes that matter (the Darwin Obj-C
> runtime, and the Gnu Obj-C runtime.)


From the point of view of the Apple fan, perhaps, yeah.

But personally I'm more interested in the Objective-C side of things.

Stephen Peters

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to
"John C. Randolph" <j...@idiom.com> writes:

> Stephen Peters wrote:
> > (As an aside, how the hell are we ever going to unify the Objective-C
> > compilers if one of the principal compiler architects can't listen to
> > criticisms with an open mind?)
>

> David isn't a "principal compiler architect." He is the author of an
> irrelevant distraction.

I disagree with that. I think POC serves a useful purpose, and is a
good piece of software. I think its author is beginning to border on
net.kook status, but that shouldn't necessarily cast aspersions on the
product.

Of course, I suppose that if we actually do manage to struggle our way
through some kind of standardization process, we can always fork the
POC development. It *is* under GPL, after all...

Helge Hess

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to Marcel Weiher
Hi Marcel,

Marcel Weiher wrote:
> Helge Hess <helge...@skyrix.com> writes:
> >I hope you understand that I do not care a lot about your 'analyzation'.
> >This is obviously style and application dependend in a huge way and your
> >sample set may have been bad.
>
> The sample is the Squeak image. It is pretty damn big and contains
> lots of code from many excellent Smalltalkers. Come up with something
> better before dismissing it!

You didn't get my point. Squeak code has Squeak style for the problem
domain Squeak is trying to solve developed by a limited set of Squeak
developers.
So it's only a sample set from a very limited domain which may not apply
for other ones (I didn't meant to imply with 'bad' that the sample
itself is bad code, but that the selection is 'bad' for the survey).

> >> It is much *more* convenient for simple blocks, and also easier
> >> to read:
> >>
> >> [[slots do] setOriginal:nil]
> >> vs.
> >> [slots do:{ :each | each setOriginal:nil].
>
> >The difficult(=inconvenient) thing to understand is the magic behind
> >'do' in HOM. Everyone easily understands what a block is, since one
> >knows compound-statements. It's a straightforward addition, IMHO.
>
> Sorry, I don't see this at all, quite the contrary. The "magic"
> behind 'do' is very easy to explain: send the message not just
> to a single object, but to every object you contain.

I admit that I have to think more about the concept, both block and HOM
and obviously haven't thought as much as you about the topic. My
motiviation is that I need to solve real-world problems with tools *I*
understand and which match my style of development which certainly is
different from yours.

I consider blocks an improvement over the current practice primarily in
the context with compareUsingFunction:context: and similiar methods.
I will take a deeper look at how to solve problems with HOM again if I
find time for that (having the other problem that NSInvocation isn't
very reliable in GNU ObjC), but what I have seen so far looks
interesting but weird, sorry.
Eg notable are also side-effects which have nothing to do with pureness
in design, like the BOOL issue or performance impacts.

BTW: the weird thing in

[[slots do] setOriginal:nil]

is that 'do' isn't named after it's behaviour. It's name is completly
artificial since 'do' doesn't do anything, in reality the name would be
something like 'gimmeWalker', since it returns a 'walker' object. This
is even more weird with 'each'.

It's difficult to explain my idea in English, but I try:
In 'normal' messaging you always have SPO, that is
subject predicate object
car driveTo: berlin
And this is destroyed in '[slots do]' which doesn't mention the subject
at all, it is not explicit as with a block parameter like 'each'.
In other words, you are 'misusing' the concept of messaging for a
different thing - blocks ;-)

Helge

David Stes

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to
Stephen Peters wrote:
>
> I disagree with that. I think POC serves a useful purpose, and is a
> good piece of software.

The nice thing with John Randolph is that you get at least a good
picture of the narrow-mindedness of the Apple fans.

I'm perfectly sure Stephen Peters's equally stupid, but he seems to try
to keep up appearances.

Stephen Peters

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to
David Stes <st...@pandora.be> writes:

> Stephen Peters wrote:
> > I disagree with that. I think POC serves a useful purpose, and is a
> > good piece of software.
>
> The nice thing with John Randolph is that you get at least a good
> picture of the narrow-mindedness of the Apple fans.

Maybe you should try to deal with people as individuals rather than
pigeonholing them into your little "Apple fan" box. You might find
that they think and make judgements independently of Apple. You might
even find that some of the people you label "Apple fans" no longer use
Apple/NeXT's software, and are working on independent projects.

Oops -- sorry, thought I was dealing with someone reasonable for a
moment. Ignore that.

> I'm perfectly sure Stephen Peters's equally stupid, but he seems to try
> to keep up appearances.

Thanks. That's really big of you.

Marcel Weiher

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to
Helge Hess <helge...@skyrix.com> writes:

>Marcel Weiher wrote:
>> Helge Hess <helge...@skyrix.com> writes:
>> >I hope you understand that I do not care a lot about your 'analyzation'.
>> >This is obviously style and application dependend in a huge way and your
>> >sample set may have been bad.
>>
>> The sample is the Squeak image. It is pretty damn big and contains
>> lots of code from many excellent Smalltalkers. Come up with something
>> better before dismissing it!

>You didn't get my point

Yes I did.

>Squeak code has Squeak style for the problem
>domain Squeak is trying to solve developed by a limited set of Squeak
>developers.

Squeak = ST-80+ What you're looking at in the Squeak image is much
of the history of Smalltalk/OO.

>So it's only a sample set from a very limited domain which may not apply
>for other ones (I didn't meant to imply with 'bad' that the sample
>itself is bad code, but that the selection is 'bad' for the survey).

That is exactly how I read you. Once again, I challenge you to
come up with a better survey, especially since there is virtually
no experience with blocks in Objective-C, whereas blocks pervade

[easy/hard to understand]

>I admit that I have to think more about the concept, both block and HOM
>and obviously haven't thought as much as you about the topic. My
>motiviation is that I need to solve real-world problems with tools *I*
>understand and which match my style of development which certainly is
>different from yours.

The real-world aspect is exactly where HOM came from! At infopark,
I had developed enum-filtersi, because I was sick of writing all
this repetitive loop code.

What makes

>I consider blocks an improvement over the current practice primarily in
>the context with compareUsingFunction:context: and similiar methods.

This is an aspect I haven't considered at all, and I am not sure HOM
will be much of a benefit. HOM was developed in the context of
iterating through collections of objects, massaging the results
in the process.

>I will take a deeper look at how to solve problems with HOM again if I
>find time for that (having the other problem that NSInvocation isn't
>very reliable in GNU ObjC), but what I have seen so far looks
>interesting but weird, sorry.

No need to apologize for your lack of understanding :-) [Really,
I am just kidding here, Helge and I know and respect each other,
just before anyone else comes jumping in]

>Eg notable are also side-effects which have nothing to do with pureness
>in design, like the BOOL issue or performance impacts.

Performance is typically better for medium to large collections,
because there is *one* set of looping code that gets reused all
the time, so it's been heavily optimized. Of course, you could
get individiual loops as fast or faster, but you usually wouldn't
bother because it isn't worth it for just a single loop.

The bool issue is a little annoying, but not much of a hassle.

>BTW: the weird thing in

> [[slots do] setOriginal:nil]

>is that 'do' isn't named after it's behaviour. It's name is completly
>artificial since 'do' doesn't do anything, in reality the name would be
>something like 'gimmeWalker', since it returns a 'walker' object. This
>is even more weird with 'each'.

This is purely a naming thing. The names used to be different, but
I changed them to reflect Smalltalk, which, by the way, also exactly
where the block messages come from. Why do you have problem with
-do but not with -do: ?

>It's difficult to explain my idea in English, but I try:
>In 'normal' messaging you always have SPO, that is
> subject predicate object
> car driveTo: berlin

You are missing the point completely, the beauty of HOM is that
it *retains* to SVO order, which blocks, for example, destroy.

More importantly, they retain the idea of *messaging*, which
is also completely lost with blocks. What happens with blocks
is that you get some arbitrary code with somewhat funky bindings
for its variables that is executed outside the its original
scope (usually at least 1 or two scopes further down), but still
somewhat in its original context.

That is *truly* wierd!

With HOM, you just have *messages*. Think of messages in terms
of communicating. As you pointed out, a normal message send
is
single-object message [ optional arguments ]

the primary change with HOM messaging is that we extend this
simple pattern to

many-objects message [ optional arguments ]

See, that wasn't too hard, was it? The nice thing is that we
can retain the same format even when addressing multiple
recipients, just like we can do in various other forms of
messaging (speaking to many people, bulk-mail, broadcast etc.)

>And this is destroyed in '[slots do]' which doesn't mention the subject
>at all,

Yes it does. 'slots' is the subject, all of them. It is the
difference between singular ( 'Du' ) and plural ( 'ihr' ).

The reason you're confused seems to be because you refuse to
accept that it is possible to address more than one object at
a time, but this is exactly what HOM does.

Of course, that is exactly why I like HOM (just like I was
fond of Backus's FP notation), the fact that it actually
allows me to operate on lots of objects at once *without
having to mention each individual object*, but instead
addressing the entire group at once.

This allows me to 'chunk' the whole group, meaning I can
abstract from unecessary detail and thus handle more of
the big picture.

>it is not explicit as with a block parameter like 'each'.

That is *no* more explicit. Where does "each" come from? Is that
in the -do: somehow? Nope!

>In other words, you are 'misusing' the concept of messaging for a
>different thing - blocks ;-)

Exactly the opposite: I am replacing a code/expression based
mechanism with a message-based one.

Think about it.

John C. Randolph

unread,
Aug 4, 2000, 3:00:00 AM8/4/00
to

David Stes wrote:
>
> Stephen Peters wrote:
> >
> > I disagree with that. I think POC serves a useful purpose, and is a
> > good piece of software.
>
> The nice thing with John Randolph is that you get at least a good
> picture of the narrow-mindedness of the Apple fans.

Narrow mindedness? Who was it that said:

"Any theory that assumes the presence of intelligence in a Next engineer
is wrong."

I have been far more patient with you than I have with other net.kooks.

-jcr

Ed L Cashin

unread,
Aug 5, 2000, 3:00:00 AM8/5/00
to
mar...@cs.tu-berlin.de (Marcel Weiher) writes:

[HH writes]


> >BTW: the weird thing in
>
> > [[slots do] setOriginal:nil]
>
> >is that 'do' isn't named after it's behaviour. It's name is completly
> >artificial since 'do' doesn't do anything, in reality the name would be
> >something like 'gimmeWalker', since it returns a 'walker' object. This
> >is even more weird with 'each'.

...


> With HOM, you just have *messages*. Think of messages in terms
> of communicating. As you pointed out, a normal message send
> is
> single-object message [ optional arguments ]
>
> the primary change with HOM messaging is that we extend this
> simple pattern to
>
> many-objects message [ optional arguments ]

I agree that "do" is misleading and weird. What about "all", since
that reflects the real meaning expressed in

many-objects message [ optional arguments ]

... rather than ...

[[slots do] setOriginal:nil]

... you'd say ...

[[slots all] setOriginal:nil]

... because the "do" or "all" message really tells the collection to
return all of the instances, and "setOriginal:" is the real "do". To
say [slots do] all by itself doesn't really do anything except return
all of the members of the collection in sequence, right?

--
--Ed Cashin PGP public key:
eca...@coe.uga.edu http://www.coe.uga.edu/~ecashin/pgp/

Note: If you want me to send you email, don't munge your address.

Marcel Weiher

unread,
Aug 6, 2000, 3:00:00 AM8/6/00
to
Ed L Cashin <eca...@coe.uga.edu> writes:

>> With HOM, you just have *messages*. Think of messages in terms
>> of communicating. As you pointed out, a normal message send
>> is
>> single-object message [ optional arguments ]
>>
>> the primary change with HOM messaging is that we extend this
>> simple pattern to
>>
>> many-objects message [ optional arguments ]

>I agree that "do" is misleading and weird. What about "all", since
>that reflects the real meaning expressed in

> many-objects message [ optional arguments ]

>... rather than ...

> [[slots do] setOriginal:nil]

>... you'd say ...

> [[slots all] setOriginal:nil]

>... because the "do" or "all" message really tells the collection to
>return all of the instances, and "setOriginal:" is the real "do". To
>say [slots do] all by itself doesn't really do anything except return
>all of the members of the collection in sequence, right?

These are good points. The current naming was chosen purely to follow
the Smalltalk naming convention:

-do 'just do it', don't return anything
-collect return the results
-select return the originals depending on the results
...

I've also had -forall and -foreach, which I like better than
'all' because the latter just indicates returning the entire
contents without actually doing anything. Both of these, however,
don't really seem to indicate the higher-order operation that
is to apply to the collection and the subsequent message, meaning
that they need to be qualified. That could be accomplished by,
for example, -forallDo, or -forallDoMessage ( -forallCollect, etc.).

I've also used -forall to indicate a cascadable HOM. In this
case, the HOM is not evaluated immediately but rather only when
a special trigger message is sent that also specifies the action.
For example:

[[[[buses forall] driver] name] collect]];

to collect the names of the busdrivers without creating a temporary array
of drivers. Instead the enumeration filters that perform the work of
HOM are chained together and evaluated one after the other.

Although I consider naming very, very important, it isn't really that
crucial to get it right from the start because we aren't talking about
a language definition issue here. If another name is better, just
change it in the frameowrk or (this is Objective-C!) just add a
cover method with the better name in a category.

0 new messages