Pharo basic language examples using Smalltalk
24 Jul 2019
Notes are based on Pharo by Example, a free book suggested by a Mooc called Live Object Programming in Pharo
Pharo basics tutorial commands
The following examples show you how to run commands, print commands and inspect commands, as well as what they do.
It looks like Smalltalk statements are finished with a fullstop.
GTPlayground open.opens a new playground window.
SmalltalkImage current aboutThisSystembrings up a window that gives you information about Pharo.
1 + 2.Returns 3 when you print it to the screen (Command-P)
Date today.Returns 24 July 2019 (or whatever the current date is).
Time now.Returns the current time in this format - 12:38:44.64634 pm
SmalltalkImage current datedVersion.Returns 'Pharo6.0 of 13 May 2016' (or the most recent version).
1/2.Inspecting this using Command-I brings up a window containing information about the object. The window contains two tabs. The first tab is called "Raw", and contains information about the variables contained within the object. In this case there are 3 variables: self = (1/2), numerator = 1, denominator = 2. In the "Meta" tab we can see what types the object belongs to. In this case the types are: Fraction, Number, Magnitude, Object, ProtoObject.
DateAndTime today.When inspecting this object, there is an additional tab called "Details" that shows a bunch of key value pairs.
Float Pi.When inspecting this object, instead of a details tab there is a "Float" tab which also shows key value pairs.
There are three types of messages in Smalltalk: Unary, Binary and keyword. Unary messages are executed first, then binary messages and finally keyword messages: Unary > Binary > Keywords. Messages that contain equal precedence are executed left to right unless parentheses are used to change the order of evaluation.
Unary message examples
Unary messages are formatted like this: "anObject aMessage"
1 class.Returns SmallInteger
false not.Returns true
Time now.Returns timestamp (2:29:33.63093 pm)
Date today.Returns todays date in this format: 24 July 2019
Float pi.Returns 3.141592653589793
"And of course:"Didn't return anything
Binary message examples
Binary messages are formatted like this: "anObject + anotherObject"
3 * 2.Returns 6
Date today + 3 weeks.Returned 14 August 2019
false | falseReturned false
true & true.Returned true
true & false.Returned false
10 @ 100.Returned (10@100)
10 $lt;= 12.Returned true
'ab', 'cd'.Returned 'abcd'
Date today < Date yesterday.Returned false
Keyword message examples
Keyword messages are messages with arguments, they look like this: anObject akey: anotherObject akey2: anotherObject2
4 between: 0 and: 10.Returned true. This means: between 0 and 10 is the message sent to the 4 object.
1 max: 3.Returns 3
Color r:1 g:0 b:0.Returned Color red
The semi colon is the cascade operator. It is used to send multiple messages to the same receiver.
ProfStef next; next.
The above code in the tutorial goes to the next page and then to the next page by sending two next messages to the same ProfStef object. This part of the tutorial was confusing to me because a transcript example was used which made it difficult to figure out what was needed. I forgot that 'next' was the message and 'ProfStef' was the object so kept trying to write "ProfStef next; ProfStef next".
Blocks are anonymous methods that can be stored into variables and executed on demand. A block is contained within square brackets. Blocks are only executed when you send it a value message/s
This is what is happening:
- First we create a variable named 'b' that does not have a value assigned
to it yet.
- We use the
:=to assign a block to our b variable. A block is a method that is executed when it is given a value.
- We give our block (now contained in our b variable) a value of 12. Everything in Smalltalk is an object, so 12 is an integer object.
- Now that the block has a value, it executes. The left hand side of the block statement is a placeholder for an object, so it becomes our 12 object.
- The right hand side of the block statement is a message that we send to our object (messages are methods that our object knows how to execute). In this case, the message we are sending to our object is '+2'. If our object was a string, then it wouldn't be able to accept the message because it doesn't know how to add 2 to itself.
- When the block is executed, it returns 14 (another integer object).
Conditionals are just messages that are sent to Boolean objects.
This is what is happening:
- First we create a binary message (anObject + anotherObject), that returns a True or False Boolean object depending on the result of the binary message (in this case, is 1 less than 2).
- This boolean object is then passed as a message to the ifTrue object which returns 100 if the boolean object it received was True. If the boolean object was not true, then it is passed to the ifFalse object which returns 42 if the object was False.
Loops are known as 'high level collection iterators' in the Smalltalk language. You can have to:do loops and to:by:do loops.
The following example is a to:do loop which returns a list of numbers from 1 to 100. Each number was converted to a string object in the process.
1 to: 100 do: [:i | Transcript show: i asString; cr].
The following example is a to:by:do loop. This loop starts with the number 100 and counts backwards by -2 until it gets to zero. The result is a list of even numbers from 100 to 0. Each number was converted to a string in the process.
100 to: 0 by: -2: [:i | Transcript show: i asString; cr].
The message 'do:' is sent to a collection of objects (collections can be an Array, Set, OrderedCollection). The do: message evaluates the block that follows for each element in the collection.
Here are a few more loop examples which replace the do: keyword messages with alternative keyword messages like ":collect", ":select" and ":reject".
#(11 38 3 -2 10) collect: [:each | each odd].returns the following array: #(true, false true false false).
#(11 38 3 -2 10) select: [:each | each odd].Returns the following array: #(11 3)
#(11 38 3 -2 10) select: [:each > 10].Returns the following array: #(11 38).
#(11 38 3 -2 10) reject: [:each | each > 10].Returns the following array: #(3 -2 10)