This lab works with some of the most powerful programming
features Smalltalk offers: blocks, collections, and the
For more details, refer to page 31-33 of your Goldberg/Robson book.
To get started, open up a workspace and try doing a "print it"
on each of the following expressions.
Bear in mind that some of these things will not be happy when you ask
them to "print it". You will get some that throw error messages and others
that complain about various things like "[] in UndefinedObject>>DoIt".
Try to guess what each will do (if they do something besides blowing up
in your face) before you print the result, and see if it did what you
expect. Understanding these simpler scenarios (why they work or why they
don't) will help when you do more complex ones below.
Simply put a Collection represents a group of objects. The
objects that a Collection is
comprised of are called elements. The arrays you probably met in
CS 1502 are one example of Collections, but Smalltalk has several more.
Here is an overview of some of the collection classes available in
Smalltalk:
Highlight the whole thing and then choose do it.
Declare
Now let's try out a Bag. Enter the following:
Do the same sequence of operations as you did for Set.
Should you get the same results?
Mess around by adding some other items to this collection.
Watch the results with the inspect.
Now, let's try out an Ordered Collection. [ For the purposes of
the this example let's make
all the elements the instances of the same class. They don't have
to be.]
Again, do it, inspect
There are several methods available for converting a collection from one
type to another.
Try printing each of these two expressions:
Sometimes it is useful, convenient, and/or efficient to look data
up by a key.
You should know the routine by now...
Close the inspector window and then invoke do it
on the following.
Objects can serve as keys. After all, numbers are objects too.
Reinspect
Collections aren't very useful until you do something with their contents.
In Java you
might have created a
The most commonly used enumeration method is
For the first, if the block evaluates to
There is also a
perform: method.Block Basics
A block in Smalltalk is a sequence of statements enclosed in square
brackets.
It can be stored in a variable or passed to other statements as an
argument,
much like an integer or a string. The statements in a block can be
evaluated
by sending it
and specifying the actual parameters for the block to use.value,
value:,
value:value:,
or value:value:value:,
[ 3 + 4 ] value
[ 3 + 4 ]
[ :x | x + 5 ] value: 1
[ :x | x + 5] value: 7
[ :x :y | x + y ] value: 3 value: 4
[ :x :y :z | x + y / z] value: 8 value: 4 value: 3
These next three can be tricky...
Look at their complaints for hints about the problem.
b := [ :x | x - 1 ]
b value: 5
b value: 20
[ [ 2 + 3 ] value ] value
[ [ 2 + 5 ] ]
The next three statements done individually will blow up but they
can go together if you pay attention to their complaints.
bb := [ [ 2 + 3 ] ]
bbValue := bb value
bbValueValue := bbValue value
The Collection Class and Friends...
What Can You Do With a Collection?
A lot! Browse through the abstract Collection and SequenceableCollection
classes some time!
Because the listing is so long, here are some of the most commonly used
methods, for your
reference. Don't bother memorizing them, because you can always look
them up in System Browser.
adding
add: newObject
Include the argument, newObject , as one of the receiver's elements.
Answer newObject.
addAll: aCollection
Include all the elements of the argument, aCollection, as the
receiver's elements.
Answer aCollection.
removing
remove: oldObject
Remove the argument, oldObject, from the receiver's elements.
Answer oldObject unless now element is equal to oldObject, in which
case report that an error occurred.
removeAll: aCollection
Opposite of addAll.
testing
includes: anObject
Answer whether the argument, anObject, is equal to one of the
receivers elements.
isEmpty
Answer whether the receiver contains any elements.
occurencesOf: anObject
Answer how many of the receiver's elements are equal to the argument.
anObject.
enumerating
do: aBlock
Evaluate the argument, aBlock, for each of the receiver's elements.
select: aBlock
Evaluate the arguments, aBlock, for each of the receiver's elements.
Collect into a new collection like that of the receiver, only those
elements for which aBlock evaluates to true.
Answer the new collection.
collect: aBlock
Evaluate the argument, aBlock, for each the receiver's elements.
Answer a new collection like that of the receiver containing the
values returned by the block on each evaluation.
accessing
at: anIndex
Obtain a value from a Collection. For Arrays, anIndex is an
Integer. For Dictionaries, it can be anything.
at: anIndex put: anObject
Replace an element in a collection with something else.
queries
size
How many elements are in the collection?
Some Basic Collections
Okay, now you try it.
Type the following into a workspace and do it:
MySet:= Set new.
MySet add: 'a'.
MySet add: 2390.
MySet add: ( Set new )
MySet as a global when asked.
Then highlight MySet and choose
inspect.
Peruse around inside of the set for a while.
Then select the MySet add: 2390 line and
print it.
What should have happened? Check
the tally to see if you where right.
Mess around by adding some other items to this collection.
Watch the results with the inspect.
MyBag := Bag new.
MyBag add: 'a'.
MyBag add: 2390.
MyBag add: ( Set new )
MyOrdered := OrderedCollection new.
MyOrdered add: 'Swimming'.
MyOrdered add: 'Baseball'.
MyOrdered add: 'Track&Field'.
MyOrdered add: 'Gymnastics'
MyOrdered and observe. Next try the following. In what order
will
the elements be in?
Mess around by adding some other items to this collection.
Watch the results with the inspect.
MySorted := SortedCollection new.
MySorted add: 'Swimming'.
MySorted add: 'Baseball'.
MySorted add: 'Track&Field'.
MySorted add: 'Gymnastics'
Conversions
MyBag asOrderedCollection
MyBag asSet
Dictionaries
MyTable := Dictionary new.
MyTable at: 12345 put: MySorted.
MyTable at: 12 put: MyOrdered ; at: 505 put: MyBag
MyTable at: MyOrdered put: MySorted
MyTable. You can
add to dictionaries this way too.
MyTable add: (Association key: #aKey value: #aValue )
Enumeration: Blocks and Collections Together
for loop and iterated through an
array.
In Smalltalk, methods that
iterates over a Collection are provided for you, so that
you don't
have to explicitly do things like create a loop variable.
do:.
do:
takes one argument, a block, and evaluates that block with each of the
elements in
the collection in turn. For example, try each of the following, and
observe the Transcript:
MySet do: [:anObj | Transcript show: (anObj) printString. Transcript cr].
MyBag do: [ :anObj | Transcript show: (anObj printString; cr ]
do: is sufficient for most enumeration tasks in Smalltalk.
However, there are other methods available that can be a little more
convenient. For example, try printing the results of these two
statements:
MySorted select: [ :anObj| anObj = 'Baseball' ]
MyOrdered collect: [ :anObj | anObj = 'Baseball' ]
MySorted collect: [ :anObj | anObj, ' is a happy String' ]
true then
that element is put a new collection of the same type.
For the second, the result of the block is used as the new element
in the collection of the
same type being created.
Perform
One last topic! Smalltalk let's you call a function just using its name.
For example, instead of the simple code "7 squared", Smalltalk
allows you to type:
messageName := #squared.
7 perform: messageName.
Try printing the above--does it give you the same as
"7 squared"?perform:with: method which allows you to
give arguments:
7 perform: #min: with: 12
7 perform: #+ with: 12
So What do you Actually Do?
To show you know how all this works, write blocks to do the following:
Your code should work something like this:
marvinBlock.
summationTwo := [ "your job..." ].
averageTwoArgs := [ "your job..." ].
averageBlock := [ "brilliant averaging code goes here" ].
marvinBlock := [ "brilliant code for doing a Marvin I/O goes here" ].
doItBlock := [ "your job" ].
funkyBlock := [ "your job" ]
summationTwo value: 1 value: 3 "should return 4"
averageTwoArgs value: 1 value: 3 "should return 2"
averageBlock value: #(1 2 4 5 3) "should return 3"
marvinBlock value: #(1 1 4) "should print 'odd', 'odd', and 'even', to Transcript"
doItBlock value: 1 value: 3 value: #+ "should return 4"
doItBlock value: 1 value: 3 value: #max: "should return 3"
b := funkyBlock value: #+. b value: 1 value: 3. "should return 4"
b := funkyBlock value: #min:. b value: 1 value: 3 "should return 1"
What to turn in
Copy the definitions of sum2, avg2, avg, etc. from your workspace and
paste this text into the BODY of an email message to your TA. Do
everything else as normal.