. .


ST 4U 318: Sketching Out a CaseStatement Object

December 7, 2012 12:33:47.791

Today's Smalltalk 4 You sketches out a case statement object in Smalltalk. Not because this is a great idea; generally, you want to use Polymorphism. However, having been asked about such a thing, we have a sketch of how to do it. 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:

Recently, I was asked about Case Statements and Smalltalk - Smalltalk does not have one (nor does it need one, for the most part) - but it makes for a small, interesting example. I had created one of these in VisualWorks years ago, but it ported pretty cleanly into VA Smalltalk (the only real difference being that #new in VA does not send #initialize to the newly created instance). I have verification that the code works as-is in GNU Smalltalk as well - not a surprise, as it's pretty basic stuff. Here's the class definition:

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

There's a convenience method to create the first case, and the collection of cases is a collection of associations (where the key is the case, the value is the execution block for that case):

case: aCondition do: aBlock
	"answer a new instance with initial condition"

	^self new case: aCondition do: aBlock

There are a few instance methods to hook up the machinery:

switch: aCondition
	"execute block previously stored"

	self switch: aCondition default: [self error: 'No Default Found']

switch: aCondition default: aBlock
	"execute block previously stored"

	| association |
	association := self findOnKey: aCondition.
	association notNil 
		ifTrue: [(self findValue: association) value]
		ifFalse: [aBlock value]

findOnKey: aCondition
	"answer association or nil"

	^cases detect: [:each | each key = aCondition] ifNone: [nil]

findValue: anAssociation
	"answer the value"

	^anAssociation value

You can then see how this kind of thing works:

| caseStatement |
caseStatement := CaseStatement case: 1 do: [Transcript show: 'one'; cr].
	case: 2 do: [Transcript show: 'two'; cr];
	case: 3 do: [Transcript show: 'three'; cr];
	case: 4 do: [Transcript show: 'four'; cr].

To actually use the statement, you do this kind of thing:

caseStatement switch: 6 default: [Transcript show: 'Could not find case'; cr].
caseStatement switch: 5.

Try that out and see what happens. You can find the code in VRGoodies (Contributed) in VisualWorks, and that code will port cleanly to at least VA and GNU (and I expect Pharo or Squeak as well).

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.

Tags: , ,

[st4u318-iPhone.m4v ( Size: 4364936 )]

posted by James Robertson


Re: ST 4U 318: Sketching Out a CaseStatement Object

[anonymous] December 7, 2012 17:36:46.802

Would have been nice if you could have listed some cases where a case statement may be legit. Personally, I tend to use case-ish stuff for data parsing where all I have is a string or other raw value and I need to create an instance of some class from it so I can use polymorphism later.

Re: ST 4U 318: Sketching Out a CaseStatement Object

[Bob Nemec] December 10, 2012 8:42:03.461

One place I found myself using case statements was in the UI code (VA in my case). That's where the Smalltalk code is acting more like a conventional program manipulating data structures.

 Share Tweet This