C/CPS 506
Comparative Programming Languages Prof. Alex Ufkes
Topic 2: Continuing Smalltalk
Notice!
Obligatory copyright notice in the age of digital delivery and online classrooms:
The copyright to this original work is held by Alex Ufkes. Students registered in course CCPS 506 can use this material for the purposes of this course but no other use is permitted, and there can be no sale or transfer or use of the work for any other purpose without explicit permission of Alex Ufkes.
© Alex Ufkes, 2020, 2021 2
Course Administration
© Alex Ufkes, 2020, 2021
3
• •
Lab #1 this week!
Poker assignment released
© Alex Ufkes, 2020, 2021
4
Let’s Get Started!
Smalltalk: OOP cranked up to 11
© Alex Ufkes, 2020, 2021 5
Objects in Smalltalk
Everything is an object. Everything is an instance of a corresponding class
A Smalltalk object can do exactly three things:
1. Hold state (assignment)
2. Receive a message (from itself or another object)
3. Send message (to itself or another object)
Message passing is central in Smalltalk.
© Alex Ufkes, 2020, 2021
6
Message Passing
Passing a message to an object is semantically similar to invoking its methods:
When a message is sent to an object:
• Search the object’s class for an appropriate method to deal with the message.
• Not found? check superclass (inheritance!)
• Repeat until method is found, or we hit
class “Object”. Much like Java.
• Stillnotfound?Throwexception.
o Did Not Understand (DNU)
© Alex Ufkes, 2020, 2021 7
Example: What is the Result? Which messages are unary? Binary? Keywords?
3 factorial + 4 factorial between: 10 and: 100
3.
6 + 24 between: 10 and: 100
30 between: 10 and: 100
30 between: 10 and: 100
1. factorial gets sent to 3, then 4.
2. + is sent to 6 with 24 as argument
between:and: sent to 30 with 10 and 100 as arguments
true
© Alex Ufkes, 2020, 2021
8
© Alex Ufkes, 2020, 2021
9
Continuing on…
© Alex Ufkes, 2020, 2021
10
Continuing study of Smalltalk:
• •
Symbols in Smalltalk More advanced syntax:
o Blocks, control flow
o A few other collections
Today
Summary: Literals
© Alex Ufkes, 2020, 2021
11
#Symbols
# followed by a string literal
• #‘aSymbol’ same as #aSymbol (quotes implied) • #‘symbol one’ #‘symbol two’
• Symbol objects are unique. Strings are not.
Meaning:
• Two identical strings can be exist as two separate objects
• For every unique symbol value, there can be only one object.
© Alex Ufkes, 2020, 2021 12
• Variablesaandbmightreferencedifferentobjects,despite the fact that the string literals are exactly the same.
• Variables x and y reference the same object. There can be no two equal symbols which are different objects.
Let’s prove it!
© Alex Ufkes, 2020, 2021 13
• Declare two identical strings, but in different ways to ensure we get different objects.
• Compare strings. ‘=‘ checks for same value, ‘==‘ checks if they are the same object.
© Alex Ufkes, 2020, 2021 14
Same value, different object!
• Symbol concatenation returns a string
• Pass the asSymbol message to a string
to convert it to a symbol.
© Alex Ufkes, 2020, 2021 15
Same value, same object!
Symbols: What’s the point?
Checking for equal string value involves comparing individual characters.
This can be costly if the strings are long. Linear time operation.
Checking if two variables reference the same object is fast – single integer comparison between addresses.
With symbols, if they reference different objects, they have different values. The same cannot be said of strings.
© Alex Ufkes, 2020, 2021 16
Symbols: What’s the point? Messages are symbols!
Given that message passing is central in Smalltalk, we would expect to be doing a lot of it.
When a message is sent to an object:
• Search the object’s class for an appropriate method o (Method whose name matches message.)
Symbols make each check constant time as opposed to linear time. Very valuable!
© Alex Ufkes, 2020, 2021 17
In Smalltalk, you can send any message to any object. If the object doesn’t know what to do with the message, a run-time error occurs.
Send message blahblah to SmallInteger object 3.
© Alex Ufkes, 2020, 2021 18
Symbol!
Blocks
© Alex Ufkes, 2020, 2021 19
Blocks
Defined with square brackets [ ] Within the [ ] is Smalltalk code.
[ Transcript show: 27; cr ].
This block contains familiar code – we show the Integer 27, and do a carriage return.
© Alex Ufkes, 2020, 2021
20
Blocks
To execute a block, pass it the “value” message
© Alex Ufkes, 2020, 2021
21
Blocks are Objects!
Highlight line, ctrl-p to print it
© Alex Ufkes, 2020, 2021 22
Blocks
Blocks are objects! They may be assigned to a variable:
• We are passing the value message to a block object.
• BlockClosure has a method called value.
Now we can execute the block using the variable
© Alex Ufkes, 2020, 2021
23
Blocks as Anonymous Functions
func := [ 😡 | Transcript show: x; cr. ].
• This is a parameter. Pharo allows up to four.
• Think about why this limit of four might exist
in practice.
Argument(s) can be passed in when we send the keyword value: message (as opposed to the unary value message)
func value: 27.
© Alex Ufkes, 2020, 2021
24
Blocks with Arguments
© Alex Ufkes, 2020, 2021
25
Blocks with Multiple Arguments
• One arg? Keyword message value:
• Two args? Keyword message value:value:
• Recall how Smalltalk interleaves arguments
© Alex Ufkes, 2020, 2021
26
value:value:value:value:value:value:value….
What can we do if we want to pass more than 4 arguments?
• Pass a single array (or some other collection) of values
• Same tricks you’d use in any other high-level language
© Alex Ufkes, 2020, 2021 27
Reminder: Terminator VS Separator func := [ 😡 | Transcript show: x; cr. ].
func := [ 😡 | Transcript show: x; cr ].
These both work. What’s the difference, if any?
© Alex Ufkes, 2020, 2021
28
Reminder: Terminator VS Separator
In Java, semi-colon (;) is the statement terminator. In Smalltalk, period (.) is the statement separator.
© Alex Ufkes, 2020, 2021
29
• • •
Thus, we do not need a period after the last statement we’re executing.
This applies to blocks as well. Period not required after the last statement in a block
Of course, it’s not illegal to have it there, just redundant
Blocks: Multiple Statements
© Alex Ufkes, 2020, 2021
30
Nice blocks, what can you build with them?
© Alex Ufkes, 2020, 2021 31
© Alex Ufkes, 2020, 2021
32
Control Structures Boolean Expressions
Control Structures: Branching/Selection In Java we have syntax (reserved words) for selection:
if (x > y) System.out.println(“True”);
else
System.out.println(“False”);
Control structures in Smalltalk do not have special syntax. They are realized using blocks and message passing!
© Alex Ufkes, 2020, 2021 33
Control Structures: Branching/Selection
They are realized using blocks and message passing!
7 > 4 ifTrue: [Transcript show: ‘This is true’].
© Alex Ufkes, 2020, 2021
34
1)
2)
7 > 4 evaluated first (why?), results in Boolean object
ifTrue: message sent to Boolean object with BlockClosure argument [Transcript show: ‘This is true’].
• •
Suggests that a Boolean object (true, false) knows how to handle the ifTrue: message.
Who can guess what the ifTrue: method is going to do with its argument?
7 > 4 ifTrue: [Transcript show: ‘This is true’].
© Alex Ufkes, 2020, 2021 35
ifTrue: must be very complicated…
• A true object receives ifTrue: message.
• It sends the value message to the argument.
• The value message executes a block.
• It really is that simple!
© Alex Ufkes, 2020, 2021 36
ifTrue: must be very complicated…
• We can see the ifTrue: method is returning the result of executing the block argument.
• Executing the code within a block is not the same as returning something!
• What is the result when we execute a block?
© Alex Ufkes, 2020, 2021 37
Evaluating Blocks
• A block evaluates to the result of its last expression.
• In this case, we have a single string literal, nothing else.
• A literal, when evaluated, is simply itself.
© Alex Ufkes, 2020, 2021
38
Evaluating Blocks
• Must evaluate to something.
• If there’s no expression, the
block evaluates to nil • nil is an object! Not a
reserved keyword.
© Alex Ufkes, 2020, 2021
39
nil
Turns out…
• If we send ifTrue: to a False object, we also get nil. • nil is an instance of the UndefinedObject class.
• Unassigned variables also reference the nil object.
© Alex Ufkes, 2020, 2021
40
nil
© Alex Ufkes, 2020, 2021
41
ifTrue:ifFalse:
© Alex Ufkes, 2020, 2021
42
• •
By now, we know this is a keyword message that takes two arguments. Both are blocks.
The block that gets executed depends on whether the message is sent to a true object or a false object.
ifTrue:ifFalse:
© Alex Ufkes, 2020, 2021
43
ifTrue:ifFalse:
© Alex Ufkes, 2020, 2021
44
ifTrue:ifFalse:
© Alex Ufkes, 2020, 2021
45
We can arrange the code to make the structure look more familiar:
• Just like in Java, this control “structure” operates on a Boolean condition.
• It doesn’t matter what that condition is, so long as it evaluates to True or False (Boolean object)
© Alex Ufkes, 2020, 2021 46
If temp <= 0, execute this block
If not, execute this block
© Alex Ufkes, 2020, 2021 47
We can write this a slightly different way – the entire structure can be an input argument to show:
Now, instead of including Transcript show: statements in the blocks, we can just use the blocks to pick a string literal object to be shown.
© Alex Ufkes, 2020, 2021 48
Different Syntax, Same Semantics
© Alex Ufkes, 2020, 2021 49
Different Syntax, Same Semantics
This is great practice – rearrange code to be as small/efficient as possible. It will help you truly understand how the syntax works.
© Alex Ufkes, 2020, 2021 50
temp := 88.
temp <= 0 ifTrue: ['Solid'] ifFalse: ifTrue: ['Gas'] ifFalse: ['Liquid']].
false ifTrue: ['Solid'] ifFalse:
This goes first!
Does not evaluate yet!
[temp >= 100
[temp >= 100 ifTrue: [‘Gas’]
ifFalse: [‘Liquid’]].
Passed to false object
temp >= 100 ifTrue: [‘Gas’] ifFalse: [‘Liquid’]
This goes first!
false ifTrue: [‘Gas’] ifFalse: [‘Liquid’]
© Alex Ufkes, 2020, 2021 51
Passed to false object
false ifTrue: [‘Gas’] ifFalse: [‘Liquid’].
Passed to false object
‘Liquid’
Finally, when all the message passes have been evaluated, we’re left with ‘Liquid’
© Alex Ufkes, 2020, 2021
52
© Alex Ufkes, 2020, 2021 Condition 53
Repetition Using Messages & Blocks
What messages are sent to what objects?
• whileTrue: message sent to block object with another block as an argument
© Alex Ufkes, 2020, 2021 54
Repetition Using Messages & Blocks
[x > 0] whileTrue: [ x := x – 1. y := y + 2. ]. whileTrue: message sent to block containing Boolean expression x > 0
The BlockClosure class understands the whileTrue: message.
The argument that accompanies the whileTrue: message is a block containing the code to be repeated.
© Alex Ufkes, 2020, 2021
55
© Alex Ufkes, 2020, 2021
56
Recursive!
• Send ifTrue: message to Boolean
• Argument is a Block object
Finally, send whileTrue: once more to the same block, with the same argument.
self value ifTrue: [ aBlock value. self whileTrue: aBlock ]
• Send value message to self, which executes it
• self evaluates to a Bool
• aBlock is the input argument first passed with the whileTrue: message
• We execute it once
© Alex Ufkes, 2020, 2021 57
Repetition Using Messages & Blocks
Much like selection, there are many options
© Alex Ufkes, 2020, 2021 58
timesRepeat:
• timesRepeat: is passed to a regular old integer • Argument is a block object (loop body)
© Alex Ufkes, 2020, 2021
59
timesRepeat: is just a wrapper for whileTrue:
© Alex Ufkes, 2020, 2021 60
© Alex Ufkes, 2020, 2021 61
For-loop equivalent – to:do:
• a is our loop index
• Can be used in the “body” of the loop
• I.e., the block
• to:do: message passed to an Integer object
• Two arguments – ending index and block representing loop body.
© Alex Ufkes, 2020, 2021
62
• Same as timesRepeat:, just a wrapper for whileTrue:
• Why is this implemented under Number, and not Integer?
© Alex Ufkes, 2020, 2021 63
For-loop equivalent – to:do: Why is this implemented under Number, and not Integer?
In the case of timesReapeat:
• We cannot execute a block 4.7 times.
• This makes no sense.
x to: y do: […]
© Alex Ufkes, 2020, 2021
64
• • •
Will count from x to y by 1. We can count from 2.1 to 4.7.
2.1, 3.1, 4.1, 5.1
• •
Iterate Over Arrays
In Java we have a different version of for loop for safely iterating over arrays.
Prevents us from accidentally going out of bounds.
• e will take the value of each element in the array nums.
• Written this way, the loop will automatically go through each element in nums.
• Don’t need to keep track of index or conditions, it’s done for us.
© Alex Ufkes, 2020, 2021
65
Iterate Over Arrays
• Send do: message to an array object with block as argument.
• Block argument is each array element
• Also works with other collections
• Speaking of collections…
© Alex Ufkes, 2020, 2021
66
Other Smalltalk Collections
© Alex Ufkes, 2020, 2021 67
© Alex Ufkes, 2020, 2021
68
We’ve seen arrays.
In Java, we have things like ArrayLists, Vectors, LinkedLists, PriorityQueues, and so on.
What about Smalltalk?
A selection:
© Alex Ufkes, 2020, 2021 69
Ordered Collection
• Can initialize as empty
• Or with some initial elements
• Can be heterogeneous!
• Transcript can print them
© Alex Ufkes, 2020, 2021
70
with:with:with:with:with:with:
© Alex Ufkes, 2020, 2021
71
Ordered Collection: Add Elements
• Send message add: to an OrderedCollection object.
• Argument is the object to append.
• Here we cascade several adds.
© Alex Ufkes, 2020, 2021 72
Ordered Collection: Add Elements
• Notice we can add a whole array!
• Arrays are objects, just like integers.
© Alex Ufkes, 2020, 2021 73
Ordered Collection: at:put:, addAll:
Notice! addAll: adds the elements of an array, not the array itself.
© Alex Ufkes, 2020, 2021 74
Ordered Collection: Removing
© Alex Ufkes, 2020, 2021
75
Ordered Collection: Removing
• Remove values. Not indexes!
• Runtime error if value doesn’t exist
© Alex Ufkes, 2020, 2021
76
Ordered Collection: Removing
© Alex Ufkes, 2020, 2021
77
Ordered Collection: select:
• Filter collection based on some criteria.
• Result is a collection containing elements
that pass condition.
© Alex Ufkes, 2020, 2021
78
Ordered Collection: reject:
• Filter collection based on some criteria.
• Remove elements that pass the condition.
© Alex Ufkes, 2020, 2021
79
Ordered Collection: collect:
• Transform each element in collection.
• i.e. perform some operation on each element.
© Alex Ufkes, 2020, 2021
80
Are we mutating the original?
© Alex Ufkes, 2020, 2021
81
Nope.
© Alex Ufkes, 2020, 2021
82
And More!
Sorted Collection
Similar to an OrderedCollection, but, you know, sorted. Operations are all very similar to OrderedCollection, but
here we can specify a sorting criteria:
[:a :c | a <= c]
• •
A block with two inputs, that implement a Boolean condition. Uses this condition to sort using heapsort/quicksort.
© Alex Ufkes, 2020, 2021
83
Sorted Collection
• Default sorting behavior is ascending order o [:a :b | a <= b]
• We can change that to descending order
• Condition can be anything that results in a Boolean
• Operations on a SortedCollection trigger re-sorting.
© Alex Ufkes, 2020, 2021
84
Sorted Collection
• Default sorting behavior is ascending order o [:a :c | a <= c]
• This is a block that evaluates to Boolean when executed
• We’re defining the condition for a appearing before c in the sequence
• Ascending order: a comes before c if a is less than or equal to c
• If block is true, a comes first.
This is just like implementing a compareTo() method in Java
© Alex Ufkes, 2020, 2021 85
Sorted Collection
Silly sorting criteria?
[:a :b | a \\ 2 = 0]
© Alex Ufkes, 2020, 2021
86
a comes before c if a is even
© Alex Ufkes, 2020, 2021
87
Modifying collection triggers re-sorting
Dictionary
© Alex Ufkes, 2020, 2021
88
• Arrays are indexed with integers; Dictionaries are indexed with any object at all.
• You’ll know exactly how this works if you learned Python in C/CPS 109
• Store key/value pairs, key can be anything.
• Very powerful, but we give up ordering (hash
table implementation)
Dictionary: Adding Entries
• Add data to dictionary using at:put: message
• Notice, keys/values can be any object.
• ByteString object as key, SmallInteger object as key.
© Alex Ufkes, 2020, 2021
89
Dictionary: Getting Value with Key
Access entries using at: message
© Alex Ufkes, 2020, 2021 90
Dictionary: Key not Found?
© Alex Ufkes, 2020, 2021
91
Not very graceful...
Try at:ifAbsent: instead
• Block argument gets executed if entry isn’t found
• Block does nothing, nil gets passed as argument to show:
• No more run time error.
© Alex Ufkes, 2020, 2021
92
Dictionary: Printing
© Alex Ufkes, 2020, 2021
93
Identity Dictionary
• When searching for a key in a regular dictionary, the result of the = and hash messages are used.
• I.e., hash to index into table, compare key to resolve collision o Remember hash tables from C/CPS 305
• An Identity Dictionary uses == message, which checks if the key is the same object
• Other than that, methods are the same
• Identity dictionary works great with symbols, less so with
strings. Why?
o Identical strings are not necessarily the same object!
© Alex Ufkes, 2020, 2021 94
Symbol Reminder
Symbols:
• # followed by string literal
o #‘aSymbol’ same as #aSymbol (no whitespace, quotes implied) o #‘symbol one’ #‘symbol two’
• Symbols are globally unique. Strings are not.
Meaning:
• Two identical (value) strings can exist as two different objects
• For every unique symbol value, there can be only one object.
© Alex Ufkes, 2020, 2021 95
Identity Dictionary
© Alex Ufkes, 2020, 2021
96
Same key value, different object
With Symbols?
© Alex Ufkes, 2020, 2021
97
© Alex Ufkes, 2020, 2021 98
There are many other classes for you to explore:
© Alex Ufkes, 2020, 2021 99
© Alex Ufkes, 2020, 2021 100