Send to Printer


ST 4U 200: A Case Statement in Smalltalk

February 29, 2012 10:59:24.463

Today's Smalltalk 4 You looks at implementing a case statement construct in VA Smalltalk. If you would like to download the code, links are below, in the walkthrough section. If you have trouble viewing it here in the browser, you can also navigate directly to YouTube. To watch now, click on the image below:

Case Statement.

If you have trouble viewing that directly, you can click here to download the video directly. If you need the video in a Windows Media format, then download that here.

You can also watch it on YouTube:

Today we'll build a simple case statement class in VA Smalltalk. Why? People are often surprised that Smalltalk does not have one, so building one is a good way of showing how Smalltalk works to a new user, while implementing a concept that's familiar to them. To get started, define a new class:

Object subclass: #CaseStatement
    instanceVariableNames: 'cases defaultCase '
    classVariableNames: ''
    poolDictionaries: ''

The cases will be stored in a dictionary, and the default case will be held in the defaultCase variable. In this example, we'll default that to a simple Transcript write. Next, let's add the instance creation code:

addAll: associationsOrDictionary
	^self addAll: associationsOrDictionary default: self simpleDefaultCase.

addAll: associationsOrDictionary default: default
	^self new addAll: associationsOrDictionary default: default

Here we allow for the definition of a default case, and for the inbound cases to be either a dictionary or a collection of associations. We'll see how that gets handled in the instance code:

addAll: associationsOrDictionary default: default
	|associations |
	associations := associationsOrDictionary isDictionary
		ifTrue: [associationsOrDictionary associations]
		ifFalse: [associationsOrDictionary].
	associations do: [:each | self addCase: each].
	defaultCase := default

Note the conversion of string keys to symbols - that ensures that we have unique keys. For the values, we simply assume any object that responds to #value. It'll probably be a block, but that's not all that could be done there. Now let's look at the execution:

caseAt: keyName
	"execute the corresponding value"
	| key val |
	key := keyName isString
		ifTrue: [keyName asSymbol]
		ifFalse: [keyName].
	val := self cases at: key ifAbsent: self defaultCase.
	^val value

Again, we convert the key if necessary, then do a lookup. If that fails, we simply use the default case. Finally, we send #value to the looked up case. That's it - we now have a case statement in Smalltalk.

Want the code? Download it here.

Need more help? There's a screencast for other topics like this which you may want to watch. Questions? Try the "Chat with James" Google gadget over in the sidebar.

Technorati Tags: , ,

[st4u200-iPhone.m4v ( Size: 5173702 )]

posted by James Robertson


Re: ST 4U 200: A Case Statement in Smalltalk

[anonymous] February 29, 2012 11:13:56.820

In the special situation where a variable will hold a symbol, and the symbol values are from a small set of predefined values, I recently did something that I like even better than a pseudo-case statement.

Using doesNotUnderstand: protocol, I rolled the ability do something like:


someValue:=mySymbol left:[...] right:[... ] up:[.. ] down:[...] ifNone:[...]. (the blocks could also be just values)

Then the doesNotUnderstand: in ByteSymbol simply picks apart the selector, looking for a match with the symbol value in any portion of the selector.

Syntactically very small, and also very readable. Only drawback is the overhead of doesNotUnderstand: processing.

Re: ST 4U 200: A Case Statement in Smalltalk

[anonymous] February 29, 2012 16:41:46.210

The usage of a case statement like that is not very readable.

I once programmed a class called SwitchStatement with the following usage:

variable := 4.

result := variable switch

case: 3 then: 'three';

case: [ 16 / 4 ] then: [ 'four' ];

case: [ :var | var == 5 ] then: [ :var | var * 2 ];

default: [ 42 ].

This produces much more readable code.

3 types of arguments are legal. The default statement is optional but the statement will throw an error if no case matches when no default is specified.

Object class was extended with the method


^ SwitchStatement for: self

 Share Tweet This