An Introduction to Pharo

Nikhil Pinnaparaju
8 min readApr 8, 2019

--

Recently I had gotten into an open source project that I found to be interesting. As I delved deeper into to it I started appreciating the originally awkward and unfamiliar landscape turned into something very intuitive and convenient. Today, I am talking about Pharo, an open-source dynamic and reflective language inspired by Smalltalk.

Why Pharo?

The fundamental beauty of Pharo lies in a simple idea — “Everything is an Object”.

Pharo is a completely Object-Oriented Programming language and this allows for a consistency in the language that I have never experienced before.

Another feature that I really fell in love with was the live coding ability. This allows us the view the data or information held by any object at any point with the code is running and it is much easier than the usual Print statements that we spam for debugging.

For a much better and elaborate article on why Pharo, I would recommend ‘Quora: Why should I choose Pharo over Python?’. I think it covers the main advantages of Pharo very well. Now let’s move on to the code part.

Getting Started

You can install Pharo from here. It has the installation for various distributions.

Open up your terminal and do the following to open the Pharo Launcher.

unzip <pharo_launcher.zip>
cd <pharo_launcher_directory>
./pharo-launcher

It should look something like this.

Pharo Launcher

We see two parts here — New Templates and Current Images.

Whats an Image? An image is like a snapshot of memory containing all the objects at a given point in time. When we launch an image, it is basically loaded and executed by a virtual machine.

The Templates are existing distributions of Pharo. We can right click on any of them choose the “Create Image” option to create an Image. Once we have an Image on our right side section we can just right click on it and press Launch.

When you start up the Pharo Launcher, you will see two sections: Templates and Existing images (which is initially empty). From the Templates side, we’ll pick on the latest stable official distribution (Pharo 6.1 at the time of writing). Right-click and choose “Create image”.

From Basics to Linked Lists

The first thing anyone who takes a course on data structures or algorithms would learn about would be linked lists, the most basic and simple data structure to store and hold data. Let’s try to build a linked list implementation in Pharo from scratch.

The first step is creating a to open the system browser (open either from tools or using keyboard shortcut — Ctrl + O + B). Right-click in the first column of the browser and select the “new package” option. Let’s name the package LinkedList for convenience.

Now let’s define our node class for our linked list. Each node in a linked list has two things, the value the node holds and a pointer to the next node. Let us call our node BasicLink for our node class. We can write the code in the bottom row of the system browser. It should show a new class tab as seen in the image where we can insert the following code.

Object subclass: #BasicLink
instanceVariableNames: 'value nextLink'
classVariableNames: ''
package: 'LinkedList'

We have now defined our nodes and the variables held in them (value, nextLink). Now let us define the setters and getters for our nodes.

To write a method, select the package we want to write in (column 1), then select the subclass to which we want to add the method (column 2), finally select the instance side option (column 3). Now in the bottom row, it should have a tab called “Inst. side method”. We can write our method now.

Inst. side method image

Let’s write a method to set a value for a node.

value: newValue
value := newValue

Let’s take a look at what happens here. In Pharo, we don’t have anything like operators or anything. Everything is a message sent. So as such, all the methods we define are messages that we send to our objects.

Messages in Pharo are of 3 types:-

  1. Unary — Messages that are sent to an object with no other information
  2. Binary — Messages with one argument to send
  3. Keyword — Messages with more than one argument to send with arguments marked by arguments (similar to **kwargs in Python).

The value: method defined is a Keyword message, as we send a newValue argument along with it. value is an instance variable that we have defined in our subclass. The ‘:=’ operator is an assignment operator which assigns the value of the right-hand side to the left-hand side. So this is our setter.

Now let’s write our getter.

value 
^value

“^” (the carrot symbol) is a return in Pharo. This unary message returns the node’s value instance variable.

Similarly, let’s write our setter and getter for the next node.

nextlink: newLink
nextLink := newLink

Above is the setter for the next node and below is the getter for it.

nextlink
^nextLink

With this, we have a basic node data structure down. Now let’s write the BasicLinkedList subclass.

Define a new subclass as we did earlier as follows,

Object subclass: #BasicLinkedList
instanceVariableNames: 'head tail'
classVariableNames: ''
package: 'LinkedList'

With linked lists, we keep track of the head and tail node, and each node has a reference to the next node in the list.

Now let’s define some basic functionality for it. The obvious first thing would be to add a node.

addLast: aLink
"add a node to the end of a linkedlist"
| link |
link := aLink.
tail ifNotNil: [ tail nextlink: link ]. "If list not empty"
head ifNil: [ head := link ]. "if list empty"
tail := link. "update last node"
^ link

There’s some new syntax here. So let’s go through it line by line.

Comments in Pharo are written using double quotes (“ ”).

| <vars> | is used to initialize our variables. So we initialize a variable link and assign it the value of the argument passed (which we assume to be a BasicLink).

ifNotNil and ifNil have implemented messages in Pharo that check if the self-argument is a Nil Object or not. What we pass to these messages are called blocks. Blocks behave as functions and are defined by square brackets ( [ ] ). Blocks can have their own local variables and take arguments. A very simple example would be,

[ 1 + 2 ] value. "Returns 3"

With this, the method should be understandable.

Now our BasicLinkedList class is usable. We can use our class in the Pharo Playground (can be opened from tools or using shortcut Ctrl + O + W). The beauty of Pharo is that we can use the Pharo Inspector (Ctrl + I) to look at all the variables of the LinkedList instance and exactly what is referencing what.

Write the following code in the playground and play around with the inspector to see what you can do.

| slist node1 node2 node3 |

node1 := BasicLink new.
node1 value: 2.

node2 := BasicLink new.
node2 value: 4.

node3 := BasicLink new.
node3 value: 4.

slist := BasicLinkedList new.
slist addLast: node1.
slist addLast: node2.
slist addLast: node3.
slist.

We can see that what the head and tail of the list slist are and we can further inspect the head and tail as well.

Finally, let’s write one last method to convert our BasicLinkedList to an OrderedCollection.

asArray
"Return a new Array containing my elements"

| arr cur|
arr := OrderedCollection new.

cur := head.
[cur isNotNil] whileTrue: [ arr add: (cur value). cur := cur nextlink.].

^ arr

The message new creates a new instance of the given class.

While statements can be written using whileTrue: and whileFalse: in Pharo and we pass a code block again as an argument. While the control hasn’t reached the last node of the linked list, we keep adding the value of our current node to our ordered collection and go to the next node.

With this, we have a very basic and usable linked list setup. Now let’s test it out.

Writing Tests in Pharo

Unit testing is an important part of writing code. In Pharo, writing unit tests is amazingly convenient and super easy to do. In this section let us look at how to write some unit tests for our code. There are 3 steps involved to writing a test case in Pharo.

  1. Create a TestCase instance.
  2. Setup the test context.
  3. Check whether the results are correct.

Step 1: Create a TestCase instance.

Let us make an instance of the class TestCase called AddElementTest.

Create a new package called LinkedList-Tests using the system browser. Then create the following subclass of TestCase.

TestCase subclass: #AddElementTest 
instanceVariableNames: ’samplelist’
classVariableNames: ’’
category: ’LinkedList-Tests’

Step 2: Setup the Case

Let us define a method setUp in our test class. This will initialize the context in which our tests will be run. This method is run before executed before the other test methods that we define in our test class.

setUp
super setUp.
samplelist := BasicLinkedList new.

This will set up a simple linked list for us that we will be using to test.

Step 3: Check whether the results are correct.

Now we can write some additional methods to test whether the code behaves as expected with no errors.

Let us write a test to ensure that only 1 element gets added when we add a node.

testAddElement
"test case to add element"

| testnode |
testnode := BasicLink new.
testnode value: 5.

samplelist addLast: testnode.
self assert: (samplelist asArray) size equals: 1.
self assert: (samplelist first) value equals: 5.

This checks whether the node’s value is correct and if the size is 1 which is what we expected.

To run your tests, open up the Test Runner in Pharo either by going to tools in the top bar or by pressing (Ctrl + O + U). This would open up the Test Runner interface. Search for LinkedList-Tests in the browser. Then simply press “Run Selected” at the bottom and check if it’s all green on the right side (it should be in this case). The Test runner will show you how many tests have been run, passed, skipped, etc.

Importable Monticello packages for the above code can be found here (https://github.com/nikhilpinnaparaju/Pharo-linkedlist).

With this, I hope I motivate a few more people to get into Pharo and try it out. Its a great project with some really motivated minds working on it. Hopefully, this helps you out with getting started. This is my first time officially blogging so do let me know if I messed anything up and do leave suggestions about some follow-ups.

--

--

Nikhil Pinnaparaju
Nikhil Pinnaparaju

Written by Nikhil Pinnaparaju

Always interested in applying Computer Science to real world problems