Maksym Prokopov personal blog
Idea is a something worth sharing

Smalltalk and its descedants

27.03.2021

Reading time: 5 min.

The Smalltalk is an extraordinary language. Firstly, this is a mother of all OOP family languages. Secondly, Java was invented as alternative for payed (sic!) programming language Smalltalk, and if IBM won the race with Microsoft a that time, things might end up very differently and Smalltalk could still be a hype.

Initially I’ve been exposed to Ruby, but only with Smalltalk I finally grasp lot’s of ideas in Ruby, so as the roots of the syntax.

No public properties

Smalltalk doesn’t have public properties at all. Though it does have getters and setters with quite the same name as the field itself. So you don’t write anything like setName, getName.

Thus you don’t have any of issues with decisions like: should I declare this variable as private, or more fancy, protected? Everything is just private, that’s it. Other objects can’t have any access to the internals apart from what is available with methods .Smalltalk even doesn’t have a syntax to access the property variable. That’s simple.

Assume you have a class Human.

call getter name value of Human

Human name.

call setter name with value

Human name: "The one".

No positional arguments for functions.

There is no such thing as positional arguments for the methods. Either one argument or named many. Nothing else. Super easy.

Function 1

Human take: "The second".

Function 2

Human take: "The second" flag: True.

This can’t be implemented clearly with Java. You will have to have a single function that takes flag with default value. So then you forced to check it later in the code.

Lisp has this property by having different bodies for different sets of arguments for the same function.

common approach to default values: initialized in getter

history
	^ history ifNil: [ history := OrderedCollection new ]

See this ifNil: method? It accepts the block, which is namely anonymous function and executes it when the target object is nil. ^ is just a return.

Every object contains ifNil method, so this getter pattern allows concise object initialization.

No if statement

Well, this is true. What you should use instead is the ifTrue: ifFalse: method with arguments one for positive, second for negative predicate and they accept anonymous functions. Everything is an object, right? so boolean operation produces Boolean object that has ifTrue: ifFalse: method that accept code blocks.

predicate ifTrue: [do this] ifFalse: [do that]

Subsequent call feature

Smalltalk has a very concise syntax, but for returning the object it provides ; operator. This enables to chain calls to the same object in a very straightforward manner.

Example for Java

new Apple() 
.method1()
.method2()

Why is there a separate syntax in Java for constructor? I don’t know. Smalltalk just calls constructor method with the same syntax as normal function call.

The same example for Smalltalk

Apple new method1; method2;

Since main thing in the language is calling methods from objects, you don’t need to have much syntax. Same concept applies to Forth language.

Anonymous functions

[ block ] - this is syntax for a piece of code

[ :anArgument | block ]

so now you can use anArgument value right in the block. Do you recognise vertical pipes argument from Ruby? This is it.

Skinny funcitons

Indeed, mostly functions in Smalltalk are really small and concise. The good reason for that is the IDE is a part of language image, this changes programmer experience dramatically. IDE is full of functionality like generate scaffold getters, setters, best in breed refactoring capabilities.

Pharo

Along with outstanding IDE support the concise function bodies is a consequense of small language footprint. No verbosity required, no types needed to be specified, funcition calls don’t ever require brackets.

Unit testing

I think unit testing that is done in Smalltalk still delivers the best experience possible.

Pharo testing

Pressing on the green dot you can re-run test.

Pharo testing

What a brilliant idea to have only assert as the test method!

Example:

testClassifyIncident
	|anIncident aState|
	aState:= ticket status.
	anIncident := ticket classifyAs: Incident service: service.
	self assert: anIncident class equals: Incident.
	self assert: anIncident status class equals: ClassifiedTicketState. 
	self assert: (ticket history includes: aState).
	self assert: anIncident service equals: service.
	self assert: anIncident agreement equals: agreement

Look at this example above! An expression is almost in plain English, almost AppleScript ;)

Less boilerplate

I have chosen the Pharo as a tool for thought, because it doesn’t require any boilerplate to start thinking on domain and experiment with entities. The REPL is awesome and allows to dig and to feel the data.

Virtual machine

Smalltalk pioneered system layer abstraction before Java. You always run your program in form of image using thin virtual machine layer.

Pure OOP object based web frameworks

I think it is really interesting how Seaside web framework works using pure objects with NO templates. This is quite interesting idea to build web interfaces.

Summary

Smalltalk is a language from the past that is still worth learning.

  1. The best in breed IDE.
  2. Consice syntax. No if statements!
  3. Pure OOP. Everything is an object and methods are messages.
  4. Convenient unit testing.
  5. Virtual machine. You can run Smalltalk on ARM CPUs, even on Raspberry PI.