Categories: Smalltalk

First Steps with Pharo Smalltalk (a beginner’s tutorial)

Having played a little (really, only a little) with Pharo, I decided maybe I can give the smallest of introductions based on my own experience so far. Smalltalk environments like Pharo and Squeak can be quite daunting, regardless of whether you are coming from a programming background or not. I will try to keep opinions and general ramblings to myself here.

Introduction

Smalltalk is an object-oriented language dating back to the 1970s. It has a very ardent following and, although it has a steep learning curve, it is fun to learn once you get into it. It has also had a big influence on several other languages like Ruby.

Some things to know before you start:

I should caution you up front that I am a Smalltalk (and, for that matter, Pharo) newbie. But I thought that I should write up what I learned before I get too deep into it, so that my experiences are still fresh in my memory and I can hopefully relate them in ways that will be useful to you.

Installation

To begin, you need to download an installation of Pharo for your platform (assuming it’s one of Mac, Linux or Windows), which you can get from the website, here: http://pharo.org/web/download.

Once you have downloaded it, extract it to the folder of your choice. When you open up the folder, you will see something like this:

Contents of the Pharo Directory
Contents of the Pharo Directory

On Windows, you can double-click the Pharo.exe executable to start Pharo. That’s it – installation done!

Looking Around

When you start Pharo for the first time, you should be greeted by the following:

Pharo first screen
Pharo first screen

Here we see a Welcome window containing some help. At the bottom is a task bar showing the windows, for now just containing an icon for the single open Welcome screen. If you prefer a light theme instead of the default dark, click the “Pharo3Theme beCurrent.” link, to change it. (I changed mine, so the following screenshots will all show the light theme).

The Pharo window looks like a mini desktop; it is in fact a little desktop environment of its own. It doesn’t interact with the desktop of the operating system, so if you want to, you can change to full screen mode.

Clicking anywhere on the desktop brings up the World menu. From this menu, select System > Settings. There is a shortcut assigned to this, as you will see, which is Ctrl + O + S. As an alternative to using the World menu, hold down Ctrl, then press ‘O’, let go (while holding Ctrl) and press ‘S’. There are menu useful keyboard shortcuts, and we will discuss a few here.

Pharo World Menu
Pharo World Menu

In the Settings Browser window that opens, look under Appearance > Desktop, and select “Fullscreen Mode“, which switches the window to fullscreen mode. Optionally, tick uncheck “Show logo…”. You can of course play around with the settings and adjust the environment to your heart’s content.

Settings Browser
Settings Browser

In the search field at the top, type in ‘author’. You should see a setting called “Author identification” being the only one shown. Replace the placeholder text (“VincentVanGogh”) with your own name. (We’re setting it now to avoid the system asking you later when we start to code classes).

author_identification

Not how, when you typed in the field, the little orange indicator appeared (highlighted in the picture) which indicates that the field has changed. You will see this a lot in Pharo. As the message at the bottom of the screen indicates, you can just hit return (or ‘enter’) to accept the change. For multiline entries, you can press Ctrl+S (accept) or use the context menu.

If you look at the window, you will see there are three window buttons in the top left. As with typical desktop windows, you can close, maximise/restore or minimise the window. If you maximise the window, you will notice that it does not cover the whole desktop, but leaves some space around it. This allows you to access the desktop and world menu even though the windows it contains are maximized.

Pharo Window Buttons
Pharo Window Buttons

Once you have finished, close the Settings Browser by clicking the ‘x’ in the top left or the window or pressing Ctrl + W. You can close any window with the Ctrl+W shortcut.

If you want to exit at any point, bring up the World menu and select “Save and Quit” if you plan to carry on where you left off, or just “Quit” if you want to discard your changes. (If you went full screen, you can also use Alt-Tab to switch windows on your OS desktop).

Starting to code

Now let’s start coding, with the simplest of examples. To do this, we are going to open two windows: one is a Playground window, which is basically a place to enter and evaluate code, and the second is a Transcript window, which is akin to a system console. We are going to write something to this console by evaluating code in the playground window.

Click the World menu and select “Playground”, or press Ctrl + O + W. This opens up an empty playground window, into which we will be entering some Smalltalk expressions and evaluating them.

Now open a Transcript window, either from the World menu (Tools > Transcript) or by pressing Ctrl + O + T and position the window next to the playground window.

In the playground window, enter the following:

Transcript show: 'Hello Pharo!'.

Now, select (highlight) the code you just entered, then right-click (context-click) and note that there are a few options in the context menu:

Evaluating code
Evaluating code

For now, we are just going to select “Do it” (the shortcut for that is Ctrl+D). When you do, you will note that the text ‘Hello Pharo!’ appears in the Transcript window.

There are three primary ways to evaluate code in Smalltalk which we will mostly use:

Let’s try another one. Don’t worry about deleting the existing code. Just carry on, on a new line. Type or paste the following code, then highlight it.

5 factorial.

Now, again evaluate it with “Do it”, or rather use the shortcut Ctrl+D. It seems as if nothing happens. Actually, Smalltalk has evaluated the code, but you didn’t see the result. Now highlight the code again, but this time, press Ctrl+P (print). This time, the result of the code prints out next to the statement. There is also a little icon, a pair of glasses, next to the result. You can click this to inspect the result in more detail.

print_eval

To dismiss the printed evaluation, press Backspace or Escape or click away from the statement.

Evaluate the statement again, this time pressing Ctrl+I (inspect), and look at the window that opens.

pharo_inspector_window

Here you can start inspecting the result. Depending on what you are inspecting, the result will look different. From here, you can also navigate to more detail about objects, etc.

One important thing to note is that you can enter expressions and evaluate them in just about any window in the Smalltalk environment. You could have entered the expression in the Transcript window and evaluated it there and, in fact, you will see that you can do it in other windows.

You may have noticed, as you type into the playground editor, that the system offers you auto-complete suggestions as you type:

pharo_autocomplete

Needless to say, this can be quite helpful when you don’t know what exactly you are looking for, but you should be aware that it is case-sensitive.

Some Basic Smalltalk Syntax

Smalltalk (in Pharo anyway) has only 6 keywords (reserved words): self, super, nil, true, false, thisContext.

The primary unit of expression in Smalltalk is the statement. A statement begins with an object, followed by a message (we typically call these methods in other OO languages), several messages or chained messages and ending with a full stop. If you are evaluating a single statement, the full stop is optional, but if you have several statements following each other, you need the full stop to tell Smalltalk where one starts and the next finishes.

Objects and consecutive messages are separated by spaces. (If you’re like me, you keep typing ‘.’ or some other separator from being used to Ruby or other such languages. Forget those; it’s spaces all the way, baby).

In the first example above, Transcript is an object known to the system, and we sent it a messsage called ‘show:’, followed by a parameter. There are three message types in Smalltalk:

When you send a message to an object, the system evaluates it and produces a result. You can send another message to the result, and have consecutive messages being sent to each result in turn. However, if you want to send multiple messages to the same object, you can chain those together with a semicolon (;), like this in what is called a cascade:

Transcript cr; show: 'That''s nice!'; cr

What happens here is that the message ‘cr’, ‘show:’ (with a parameter) and again ‘cr’ are being sent to the Transcript object in turn (‘cr’ causes a carriage return to be printed). Without the semicolon, the system would try and send ‘show:’ to the result of ‘cr’ and that would fail. (Note how the single quote escapes itself in a string – I recognise this from ABAP!)

You have probably noticed that a string is represented by a series of characters in single quotes. Any text in double quotes, on the other hand, is treated as a comment and is not evaluated by Smalltalk. Try it; you will find that it just evaluates to nil.

"This is a comment. The system ignores it, but it's good for readers of code!"

Variables are declared before they are used: you can put one or more variable names between pipes (e.g. |var1 var2 …|). In the playground, however, you can assign variables without first declaring them.

To assign a value to a variable, use ‘:=’ (‘=’ by itself compares two values). Let’s try with an example. Copy and paste the following two lines into the playground window, select them and evaluate them:

page := ZnClient new get: 'https://ceronio.net'.
Transcript show: page.

If all went well (and I see no reason why not, unless you’re behind a proxy), then you should see the raw HTML of the front page of this website appear in the Transcript window.

You should understand that new is not a syntax construct; it is not a keyword of the language. It actually sends a message to the object, instructing it to make an instance of itself; the implementation for this method is defined in a base class of all classes.

The last thing you should know about, before we look at two more syntax constructs, are symbols. A symbol is a kind of string, more of an identifier really, which you can use for comparing values. They are written with a preceding hash like ‘#local’ or ‘#global’. They are useful because, unlike strings, you can use a symbol as an identifier which will always be guaranteed to be equal to the same symbol. That is not true for strings; even strings comprising the same text could be different objects in memory, so they cannot be reliably compared. (Try sending the message ‘hash’ to an object, e.g. “#lucky hash” to see the unique identifier for the object).

#lucky hash = #lucky hash. "This will always be true"

More Syntax: Array and Block by Example

Two more important constructs of the language syntax are literal arrays and blocks. Let’s look at an example that employs both:

#('talk' 'a' 'little' 'louder') collect: [ :word | word asUppercase ]

The brackets preceded by a hash and containing some items make a literal array (that is, you don’t have to instantiate the Array class and add items with messages; the language provides a special syntax for it). Here we defined an array with four strings.

Next, we send the ‘collect:’ message (a keyword message) to the array, which takes a block as an argument.

A block is a piece of code in square brackets. It contains statements that are not executed by default. Blocks act as closures; this makes them useful for passing code around between objects for evaluation (you may have come across the idea in other languages, where you can pass functions around, like in Javascript, or lambdas in functional languages). You can evaluate the code in a block by sending it the value message. In fact, what happens above is that the ‘collect:’ message will take the given block and evaluate it for each element in the array.

Blocks can receive a list of variables as input at the start, each prefixed by a colon. The rest of the code after the pipe (|) is the code that will be evaluated. So in the block above, a variable called ‘word’ is declared. The statement following the pipe takes the value passed to it (which will be a string) and transforms it to upper case.

If you evaluate the entire statement above, you will get back a new array in which each of the strings has been capitalised.

array_bracket_example

Just for laughs, try highlighting only the block or only the array and inspect each in turn, just to see how the system sees each of them.

Inspecting the environment with the System Browser

As I said at the start, the Smalltalk environment is a running system. The environment is preloaded with a large number of classes. Smalltalk offers a tool called the System Browser with which you can inspect the system. (This is an important tool, so we’re talking about that for a minute).

world_menu_system_browser

We could open the System Browser from the World menu; in fact, it’s the very first item on the list. (You can use, and should memorise, the shortcut Ctrl + O + B to open it). But we’re going to go a bit of a roundabout way to get to the System Browser:

Navigating to the System Browser from an Inspector

With your example code in the playground open, highlight the block (the bit that reads “[ :word | word asUppercase ]”) and inspect it (Ctrl+I). If you did it already from the suggestion above, you would now have an inspector window from evaluating the block, showing the following inspection on the BlockClosure object you just inspected, where under the “Raw” tab, you see the variables of the object:

inspector_on_blockclosure

Now switch to the “Meta” tab:

inspector_to_browser

On the left you see the list of classes in the BlockClosure class hierarchy. On the right is a list of methods defined for the selected class. If you click on the “BlockClosure” entry on the left, then press Ctrl+B (or right-click and select the same option), a new System Browser window opens.

Looking at the System Browser

OK, I took you the long way round to get to the System Browser, but it’s good to know that there are multiple ways of inspecting and accessing values in the system. Now that we have the browser open in front of us, let’s look at what it give us:

system_browser

This may not be the most intuitive tool to use, but it’s quite powerful, and it will allow us to create classes and methods as we will see further on. For now, we’re just going to use it to examine the system.

On the top row, first we have a list of packages. Classes are organised in packages. If you select a package, the list of classes belonging to the package is shown in the next pane. Selecting a class, in turn, allows you to see the methods it defines, which is what the next two panes are about. Note that clicking on a class alternatively selects and deselects it. When a class is selected, you see its definition in the code pane below.

Methods are grouped by their function; these groups are called protocols (sounds more mysterious that in it), which you see in the third pane on top. This grouping is (I think) a rather arbitrary categorisation as you can assign methods to protocols as you choose. You can click on the “– all –” pseudo-group, or browse methods by their protocol, which gives you some idea of the kind of functionality you can expect.

Take note also of the three toggle buttons below the class list, labeled “Hier.”, “Class” and “Com.” respectively. The first, when selected shows the inheritance hierarchy of the selected class. (When it’s selected, the package list is disabled, so remember to toggle it off again to browse packages).

The second, the Class button, allows you to browse the so-called “class-side” (a Smalltalk community naming) members of the class. Class methods and variables are, effectively, like static members you know from other OO languages.

Lastly, the “Com.” or “Comment” button, when toggled, opens another pane next to the code pane that shows the comments (documentation) of the class.

Back to methods: When you click on a method, the code pane at the bottom shows you the code of the method implementation. Usually, these are documented with comments, so you can just read through the code to find out what they do.

So, now that you know the basics of the System Browser, you can spend some time (probably much time) discovering all that the Smalltalk environment has to offer. Note that certain classes are represented by different icons. This is a pretty cool feature; it allows you to identify the function of a class in many cases (e.g. graphical or collection elements, base classes, etc.). I haven’t figured out how these icons are assigned; I will write on that when I do.

Loops and Conditions (Flow Control)

Let’s take a break from the System Browser for a while and talk about how you write useful logic in Smalltalk using loops and conditionals. We’ll use some examples to demonstrate a few. Again, unlike other languages you may be used to, loops and conditionals are not language constructs in Smalltalk. That is, there are no keywords for them; they are in fact messages you send to objects.

Evaluate the following code snippets; inspect the results or just parts of the code to understand what each part evaluates to.

‘If’ Conditions

Suppose we want to branch between options. Evaluate the following:

age := 35.
age > 35 
  ifTrue: [ Transcript show: '80s music is the best!' ]
  ifFalse: [ Transcript show: 'What is a flock of seagulls?' ]

What happens here? Well, the ‘>’ (greater than) message, you may have guessed, is a binary message. The result of this message is a Boolean object; in this case the built-in ‘false’. Next, we are sending a message to this Boolean object; each with a block of code to be evaluated depending on the outcome.

(You can open up a System Browser window, navigate to the ‘Objects’ package, and find the Boolean class inside. Look at the messages it defines. Remember when I said keyword messages are like method signatures? You will find the “ifTrue: ifFalse:” and “ifFalse: ifTrue:” messages inside, along with other possible evaluation results (e.g. for only true or only false).)

boolean_browser

Loops and repetition

Loops can be handled in a different number of ways. Earlier we saw how to iterate over a collection by sending ‘collect:’ to an Array, which looped over the items in the array, evaluating a given block for each item and passing the item to the block.

The easiest way to repeat something multiple times in Smalltalk is to send timesRepeat: to a number, passing a block of code as the argument. The code will be executed as many times as the value of the number.

10 timesRepeat: [ Transcript show: 'I like Pharo!'; cr ].

(This reads extremely naturally, almost like spoken English!)

You can also create an Interval by sending to: to a number, then sending do: to the resulting Interval, passing a block of code as the argument.

1 to: 5 do: [ :n | Transcript show: 'Mambo number ' , n asString; cr ].

(In the example above you see how to concatenate strings; you can use the ‘,’ (comma), a binary message with which you join a second string to the first).

Instead of while, which you may know from other languages, you can use a Smalltalk block that will evaluate to true or false, and send whileTrue: or whileFalse: to it, passing another block with the code you wish to execute for the duration of the condition:

n := 5.
[ n > 1 ] whileTrue: [ n := n - 1 ].

There are many different ways to do loops but these basic examples should get you started.

Defining Classes and Methods

Whew, this has been a gruelling tutorial, but we’re not done yet! We haven’t even defined our own classes but, fortunately, we’re going to do that now.

In this tutorial I won’t attempt to go into depth to explain object orientation in Smalltalk; I don’t think I am qualified to do that yet and, besides, that would be the subject of a whole tutorial on its own. Here we will just look at the tools and how to accomplish the basics.

Let’s go to the System Browser again (Ctrl + O + B, or use the World menu). We are going to use the System Browser to create a package, create a class inside the package with a method or two and, finally, try out our class in a Playground.

Creating a package

With the System Browser open, right-click (or context-click) on any existing package, or in the empty space below the packages, and choose “Add package…”.

create_package

This brings up a dialog in which you can enter the name of your new package. It doesn’t matter; give it any name and click “OK” or press Enter:

new_package_dialog

 

Creating a class

With your new package highlighted, you will notice that in the code pane below, there is a bit of code representing a class definition. This is a piece of template code into which you can type your own values. It has already been pre-populated with the name of your package into which the class definition will be placed.

new_class_template

 

Here you can put in your own class name, change the super class if you wish and add a list of instance and class variables as you require. (The list of instance variables is just a space-delimited list).

Change the code to look like the following (or just copy and paste):

Object subclass: #MotorCar
  instanceVariableNames: 'speed enginesound'
  classVariableNames: ''
  package: 'ceronio.net'

Note how, when you change the contents of the code pane, the orange indicator in the top right showing that the contents have changed. When you right-click and press “Accept”, or just Ctrl+S, the contents of the pane is saved, and you will immediately see the newly created class in the browser.

(Also, observe that in Smalltalk, creation of a new class is not a matter of syntax; there are no keywords to create a class. In Smalltalk, classes are also objects. So, to create a new class we send the ‘subclass’ message to an existing class, which will respond by creating a new subclass).

new_class_created

 

Adding methods

You now have a class, but no methods yet. With your new class highlighted, click on the text that says “no messages” in the next pane. You will see that the code pane below changes, showing you the template code for a new method; the method pattern (it’s not a method name) in bold at the top, followed by a comment string, then a local variable declaration and, finally, the method body.

no_messages

 

Replace the template code with the following:

initialize
  "Set a default speed and sound"
  speed := 40.
  enginesound := 'Vroom vroom'.

Now, again, hit “Accept” (Ctrl+S). You will see that, right away, the ‘initialize’ method appears at the top. It is automatically grouped into the ‘initialization’ protocol. This is because it is actually a method that has been defined in a parent class, where it was already grouped like that. Also, the green arrow next to the method indicated that it is actually defined in a super class and that we have overridden it. The ‘initialize’ method is called whenever a new object is created (that is, when you create a new object by sending the ‘new’ message to a class), so it is a convenient place to initialize variables.

initialize_method

 

Now we will create a second method. Click on the ‘– all –‘ pseudo-protocol (a group containing all the methods of the class) and replace the contents with the following:

drive
  "Make the car go"
  Transcript show: 'Going at ', speed asString, ' km/h - ', enginesound, '!'.

After again accepting the input with Ctrl+S, you will see ‘drive’ listed under the methods, and a new protocol, “as yet unclassified” appearing in the protocol list. We’re not going to worry about creating a new protocol for out new element at this point (maybe in a future tutorial) though you are welcome to play around with the functionality.

Test-driving the class

Let’s take our MotorCar for a spin.

Open a Playground (Ctrl + O + W) and a Transcript (Ctrl + O + T). In the playground, enter the following:

car := MotorCar new.
car drive.

Highlight the code and press Ctrl+D to ‘Do it’. In the Transcript window you should see the text “Going at 40 km/h – Vroom vroom!” appear.

testdrive_car

The Morphic UI

Before finishing off this tutorial, I will tell you just a little bit about the user interface.

“Morphic” is the name given to the user interface library/toolkit (call it what you will) that Pharo is built on. All the graphical elements you have interacted with so far, the Playground, Transcript, System Browser and all the elements that make them up (menus, panels, lists, buttons, etc.) are all instances of “morphs” (the classes that make up the elements of the graphical UI).

You can get information, manipulate, and do all sorts of unholy things to any element you see in the environment. Let’s take a look:

If you hold down Alt and Shift on your keyboard and click on any element on the screen (this is called a “meta-click“), you will see a collection of buttons pop up around it, with a description along the bottom of the element you have highlighted.

nautilus_container_halo

This is called the “morphic halo“. It presents you with a number of options to manipulate the element including resizing, rotating (in some instances), recoloring, moving and more.

With each consecutive click, the container elements are selected, allowing you to cycle through all the elements until the topmost container of the window.

nautilus_morphic_halo

One of the most useful features on the morphic halo is the debug button. This is the icon that looks like a wrench. When you click this, you get a menu with a few options, including “inspect morph“, which opens up an Inspector window on the morph for you to examine its properties. Another option on this menu is “browse morph class“, which opens up a browser on the underlying class of the morphic element.

So, apart from allowing you to modify any user interface element, the morphic halo offers a great way to learn about the different types of morphic elements and how they are assembled through inspection. It also demonstrates what I said earlier, namely how the system is a very malleable and introspective environment.

Next Steps

This tutorial has but scratched the surface, but has hopefully been a useful introduction into the world of Smalltalk. Mainly, you should have gained some hands-on, practical experience navigating around the Pharo Smalltalk environment and learning some basics of the language. Moreover, the tools you learned about here give you a good idea of how you can learn more about the system by examining it.

The environment can be very daunting to newcomers (though I think Pharo is less daunting than Squeak) but, with practice and effort, it should provide a productive way to code, for which I will hopefully provide some more detailed tutorials in future.

Further Reading

Make sure to check out some of the resources that I referenced in the writing of this tutorial:

Also, be sure to check out the following jaw-dropping video by Avdi Grimm, with a focus on the testing tools built into Pharo: 7 minutes of Pharo Smalltalk for Rubyists.

Article info



Leave a Reply

Your email address will not be published. Required fields are marked *