Tiny, yet so beautiful
The smallest piece of great Pharo code
How do you introduce an unknown, alternative programming language to other developers ? One way to do so is by showing lots of small examples. That is what we did in Elegant Pharo Code — Beautiful & Powerful One-liners, Expressions and Snippets.
But as noted at the end of that article, real Pharo programs are different. Object oriented programming and design are hard to teach, with code living in multiple places.
Another approach is to show and explain actual, coherent examples. That is the primary subject of most articles in the Concerning Pharo publication.
Real working code also contains some boilerplate code. This housekeeping stuff often obfuscates the really beautiful parts.
What if we turned the question upside down ?
What would be the smallest piece of great Pharo code ? Something tiny yet very beautiful ?
Here is one gem that I found and instantly fell in love with.
Bits & Bytes
First, we need to set the context. Even though Pharo is a high level programming language, it is surprisingly well suited to do binary coding, to manipulate bits & bytes. A typical task is to work with bit masks. Classic bitwise operations like bitwise AND, OR and NOT do of course exist on Integers. But directly accessing individual bits is just as easy.
| mask |
mask := 0.
mask := mask bitAt: 3 put: 1.
mask := mask bitAt: 7 put: 1.
mask
We start the mask all zero and then set the 3rd and 7th bit to 1 (Pharo counts from 1, Integers are immutable). The result is 68, or 1000100 in binary. Retrieving a bit is even simpler.
mask bitAt: 3
When interpreted as a flag, a Boolean property, a bit value of 1 is considered to be true, while a bit value of 0 is considered to be false. In our models in Pharo, flags will be Booleans, so we need to do a simple conversion.
| mask |
mask := 0.
mask := mask bitAt: 3
put: (self flag1 ifTrue: [1] ifFalse: [0]).
mask := mask bitAt: 7
put: (self flag2 ifTrue: [1] ifFalse: [0]).
mask
We are assuming our model object has #flag1 and #flag2 methods returning a Boolean value. The conversion when testing a bit is trivial.
(mask bitAt: 3) = 1
Although it is cool that we can write the inline test to do the conversion, it is not very elegant, ugly even. What if we introduced helper methods to clean things up a bit ?
flag1AsBit ^ self flag1 ifTrue: [1] ifFalse: [0]
Now we can write
| mask |
mask := 0.
mask := mask bitAt: 3 put: self flag1AsBit.
mask := mask bitAt: 7 put: self flag2AsBit.
mask
This is better, but it still is a lot of work, adding an additional method for each flag. And the test remains so silly, right ?
Booleans
Here is how Booleans are implemented in Pharo. They are objects like everything else, of course. There is an abstract class Boolean with two concrete subclasses, True and False.
Object
+--> Boolean
+--> True
+--> False
These classes have no state, they are pure behaviour: they react differently to different messages. The system makes sure that there is only one instance of each these two classes, ever, aptly named true and false. These are like predefined constants (and 2 out of the 5 reserved words in the language). They are instances respectively of classes True and False, that have common
superclass Boolean.
All logic is defined as messages sent to these classes. For example, consider the implementation of #and:
Boolean>>and: alternativeBlock
"Non evaluating conjunction -- If the receiver is true, answer the value of the argument, alternativeBlock; otherwise answer false without evaluating the argument" self subclassResponsibility
False>>and: alternativeBlock
"Non evaluating conjunction -- answer with false since the receiver is false" ^ self
True>>and: alternativeBlock
"Non evaluating conjunction -- answer the value of alternativeBlock since the receiver is true" ^ alternativeBlock value
The superclass implementation is the design specification. The 2 concrete implementations are elegantly simple. Note that alternativeBlock is a piece of delayed code, a lambda or closure, denoted using square brackets. And before you ask, yes, the compiler does some magic to maintain a good level of performance.
The Gem
Now we can finally introduce the tiny piece of code that is so beautiful: the #asBit message.
Boolean>>asBit
"Convert me to an Integer using 1 for true and 0 for false" self subclassResponsibility
False>>asBit
"Return Integer 0 since I am false" ^ 0
True>>asBit
"Return Integer 1 since I am true" ^ 1
“Is that it ?”, you are probably asking. Yes it is (I told you it was tiny).
Why is this so great ?
Let me tell you the various reasons why I think this is so cool. There are technical, design, philosophical and even social reasons.
It is tiny
It is so small, trivial even, that it is easily overlooked. Yet it is really great.
The message name is also short, to the point, easy to understand and follows common conventions.
It solves our problem
Given this method, we can rewrite our problematic code and live by the DRY (don’t repeat yourself) rule.
| mask |
mask := 0.
mask := mask bitAt: 3 put: self flag1 asBit.
mask := mask bitAt: 7 put: self flag2 asBit.
mask
In our model we keep working with booleans, yet at the moment we need a bit representation, a simple unary message does the necessary conversion.
The new method is certainly generic enough to be useful in many situations and thus deserves its place in the main system.
It is impossible in most programming languages
In most other programming languages, primitive types are not real objects, they are special. But even if some languages make them real objects, they do not allow you to add behaviour to them, they are closed to extensions.
In Pharo you can add methods to system classes, in a clean way, which gives you great power to build the system you want, by extending what is already available.
It uses method dispatch
Notice how the test is completely gone ! Where did it do ? How is that even possible ?
It uses Pharo’s method dispatch, the core technique where an identical message invokes different implementations depending on the class of the receiver. Sending #asBit to true results in the system selecting one implementation, while sending it to false results in another. This is also called polymorphism.
Making effective use of method dispatch is key to great object designs. Excessive use of tests, conditionals and especially case statements is often an indication that your design could be improved.
It touches the core of object programming
Object programming is about sending messages between objects, more so than it is about data abstractions. Behaviour is more important than internal structure.
In a good object program, your objects are intelligent beings that know how to do what you want them to do. And if they don’t, you extend their behaviour. Objects are much more than data structures.
Manipulating objects using their pre-existing API often leads to repetitive code. Extending their behaviour can solve this elegantly.
It shows that even stateless objects are powerful
As mentioned before, note how the 3 classes involved have no state, no instance variables. Still, their behaviour does really matter, makes a functional difference and solves actual problems.
It shows that even constant methods are powerful
Not only are the Boolean objects stateless, the #asBit method itself is constant as well, it just returns a constant value, no matter what. And again, the implementation does really matter, makes a functional difference and solves actual problems.
It has cool comments
Documentation is necessary. In this particular case, talking about ‘me’ and ‘I’ or your ‘own value’ is pretty cool, philosophically, isn’t it ?
It has unit tests
Pharo has a large suite of unit tests that are run each time something changes, to ensure that no functionality is being broken. Even a method as simple as #asBit needs its unit tests, see the 2 implementations of #testAsBit who basically assert the following 2 statements:
self assert: true asBit = 1self assert: false asBit = 0
Unit tests also constitute documentation that is automatically maintained and thus always correct.
It was added recently
This code was added at the very end of 2012 and became part of the main Pharo image ever since. This is important because it means Pharo is constantly evolving.
It is only in active use in Pharo
The way Boolean works in Pharo is inherited by all Smalltalk implementations. The #asBit method is only in active use in Pharo, though it could be added to any of them. As a 21st century, fast evolving, actively developed system, Pharo accepts and uses good ideas like this one almost daily.
It was added by cool people
Pharo is being developed by a diverse, international community. One of our mottos is ‘Pharo is yours’, meaning that you are encouraged to see it that way, to contribute even small improvements.
In this particular case, Igor Stasenko (from Ukraine) and Camillo Bruni (from Switzerland) added this while working together at INRIA’s RMOD Lab in France. They probably did not invent it themselves, but they knew very well how cool it was, that they should use it and that it deserved its place in the image. Thanks guys !
For all of the above reasons, this tiny piece of code is an excellent example of truly great Pharo code.
The End
I hope you enjoyed this story. I hope I was able to make my point. Thank you for your time.
Do you have a favourite piece of code ?