Sections

Today we are bringing together selectors as blocks from the last post and currying discussed before, to produce something pretty neat: sections.

We begin with an example. Using asBlock from the last post, we can write

#> asBlock

to mean a block comparing two arguments. If we curry it with a number, say 42:

#> asBlock curried value: 42

we get a one-argument block which, when invoked, tells whether 42 is greater than the argument. We could use it as a regular one-argument block, for example, with select:

#(1 20 50 43 11) select: (#> asBlock curried value: 42)

Of course, this by itself isn’t particularly exciting. [:each | 42 > each] would have done the same, and without excessive mental acrobatics.

Without being too concerned about the form for now, let’s consider what we have just done by writing that expression. We took an operator (a binary selector) and produced a function (a block) which is an application of that selector to 42 on the left and the function argument on the right. In Haskell such a construct is called a left section of an operator. Similarly, a block applying #> with 42 on the right and the argument on the left would be a right section. This is an interesting concept—apart from the unwieldy shape it had in our code. Let’s fix that.

We add two methods to the system, one to the Symbol class, the other to Object.

Object>>~ mustBeSymbol
	| block |
	block := mustBeSymbol asBlock.
	block numArgs ~= 2 ifTrue: [self error: 'invalid selector'].
	^block curried value: self

Symbol>>~ anObject
	| block |
	block := self asBlock.
	block numArgs ~= 2 ifTrue: [self error: 'invalid selector'].
	^[:a :b | block value: b value: a] curried value: anObject

This defines ~ as a section operator. Sent to a symbol, it produces a right section, sent to anything else with a symbol as the argument—a left section. We can now rewrite the example as

#(1 20 50 43 11) select: #> ~ 42

or to select the opposite

#(1 20 50 43 11) select: 42 ~ #>

This is more interesting than just currying (and can if fact be rewritten to not rely on currying). It will work for any binary or one-argument keyword message:

Transcript ~ #show:

is a block that writes its argument to the transcript.

#print: ~ foo

produces a block writing the printString of whatever was in the variable foo to the argument, which must be a stream-like object.

#, ~ ', hello!'

is a block that appends ‘, hello!’ to the argument, and

'Hello ' ~ #,

prepends ‘Hello ‘ to it. In general, we can think of a tilda as “stick the selector and the object together, and the object missing for this to be a complete message send will be provided when the block we create is called”.

5 thoughts on “Sections”

  1. Nice post, keep em coming. You make me appreciate the power of Smalltalk more and more by how easily these concepts are to add. It’s also interesting to see these more functional concepts added, it’ll be interesting to see some more real world examples where such things would come in handy.

  2. Vasilli,
    These are interesting ideas, but they would be a bit easier to understand if you would include the results of evaluating each example.

    BTW, as a former APL programmer (a functional language from the 60’s), I’ve often thought that Smalltalk would be greatly enriched by some of the matrix and operator capabilities of APL.

    Good luck with your new job.

    Regards…Rich Demers

  3. Brian,
    I’ve been aware of F-Script for some time, but I’m more interested in seeing some of the good features of other languages (like APL) supported in the Smalltalk that I use (i.e., VisualWorks).

Comments are closed.