Aha! How to get rid of Blocks in Smalltalk.

Richard A. O'Keefe ok at atlas.otago.ac.nz
Thu Apr 27 02:30:07 UTC 2000


David Farber <dfarber at numenor.com>
describes a restriction on blocks (one message send per block)
and the reason for it (making a callback-based GUI work).

While I haven't written as much Smalltalk code as most of the people on
this list, such a restriction would wreck most of it (as indeed it would
wreck much of the code in "Inside Smalltalk", my primary reference).
The code could be rewritten.  However, doing so would make it much less
clear.  Let's take one specific example.

DomNode>>
select: aBlock
   |result|
   result := self clone privateZap.
   1 to: self size do: [:index|
      |element|
      element := self at: index.
      (aBlock value: element) ifTrue: [result addLast: element]].
   ^result

The outer block clearly contains more than one message send.
Let's rewrite this method so that each block does only one message send.

select: aBlock
   |result|
   result := self clone privateZap.
   1 to: self size do: [:index|
      self addElementAt: index to: result if: aBlock].
   ^result

addElementAt: index to: result if: aBlock
   |element|
   element := self at: index.
   (aBlock value: element) ifTrue: [result addLast: element]

Presented like this, it's not _too_ bad.  But in a Smalltalk browser,
this change is truly dreadful, because part of the code, having no
genuine independent existence of its own, is no longer visible.

There are problems with the revised code.  If only I could write
   ...
   1 to: self size do: [:index|
       self add: (self at: index) to: result if: aBlock]
   ...
addElement: element to: result if: aBlock
   ...
the code would become simpler, and the new method could be moved to
another class, giving the simpler code
   ...
   1 to: self size do: [:index|
      result addLast: (self at: index) if: aBlock]
   ...
but that would involve two message sends in the block, not one.

And the sad thing is that it wouldn't actually buy me anything.

The problem that David Farber identified is that if you need to fix
some code in a method, you just hack away in a browser, but if you
need to fix some code in a BlockContext that has been squirrelled
away somewhere, you are sunk.

One problem with his solution is that it doesn't seem to solve the
problem.  If I have an instance of
	[importantData discard]
tucked away as a callback somewhere, and the code should _really_
have been
	[importantData archiveOn: someFile]
then the fact that it's just one message send isn't going to help
very much.  We'd still need a BlockContext browser or inspector that
would let you edit the code it was running.  (Come to think of it,
I can't find any way of viewing the code while inspecting a BlockContext.
_Is_ there a way in Squeak?)

Or we could change [.] to {;} and call the new syntax Borneo...





More information about the Squeak-dev mailing list