Exploring the Smalltalk Collections API in unit tests using Pharo 8.0
Learn a little Smalltalk, and you might thank
A Little Smalltalk for the Holidays
I wanted to write a blog for the holidays to meet my commitment of writing one blog per month. I had some experiments I had written using Pharo 8.0 that I decided to organize into individual tests so I could blog about them. The experiments were a Smalltalk port of the methods I had written about in the following blog about Eclipse Collections.
My 25 favorite methods from the Eclipse Collections API
Out of hundreds of possibilities, these are some of my favorite methods available on the Eclipse Collections API.
The Smalltalk Collections API is amazing. I didn’t realize how amazing the Smalltalk Collections framework was until I started programming in Java. The absence of a rich collections API made me long for Smalltalk in my early days as a Java programmer. Smalltalk can help you become a better programmer in any programming language you code in. At least, this has been my personal experience. Learning Smalltalk in 1994 prepared me for the eventual inclusion of lambdas and Streams in Java, nearly twenty years later when they were released in Java 8 (2014).
Learn Smalltalk in Y minutes
For a quick intro to Smalltalk syntax and methods, check out the following link.
Learn X in Y minutes Where X=Smalltalk
Smalltalk is a fully object-oriented, dynamically typed, reflective programming language with no 'non-object' types…
Syntax used in the examples
In the examples in this blog I will use temporary variables (
| variable1 variable2 |), assignment operator (
:=), statement ending (
.), unary messages (e.g.
asBag) , binary messages (e.g.
=), keyword messages (e.g.
assert:equals:, etc.), a reserved word (
self), String literals (e.g.
‘banana’), Character literals (e.g.
SmallInteger literals (e.g.
2), and code blocks(
[ :parameter | expression ]). Code blocks are the equivalent of lambdas in Java, and are full lexical closures that have a single type in Smalltalk (
BlockClosure in Pharo).
This is what it looks like creating temporary variables, instantiating objects and calling methods on objects in both Java and Smalltalk with assignment.
Object param1, param2, param3;SomeClass object = new SomeClass();
Object result1 = object.method();
Object result2 = object.withOne(param1);
Object result3 = object.withOneTwo(param1, param2);
Object result4 = object.withOneTwoThree(param1, param2, param3);
| object param1 param2 param3 result1 result2 result3 result4 |object := SomeClass new.
result1 := object method.
result2 := object withOne: param1.
result3 := object withOne: param1 two: param2.
result4 := object withOne: param1 two: param2 three: param3.
Smalltalk Collection methods covered in this blog
The following are the iteration patterns I will cover in this blog. I decided to keep it limited to a set of basic patterns. The full source for all examples is here.
The following are additional methods I used in the tests.
The following are the data structures I used in the tests.
Smalltalk Iteration Patterns
select: can be used to a filter a collection inclusively. The method takes a one-argument block that returns a
reject: can be used to a filter a collection exclusively. The method takes a one-argument block that returns a
collect: can be used to transform a collection. The method takes a one-argument block that returns any type (aka
flatCollect: can be used to flatten and transform a collection. The method takes a one-argument block that returns a
Function). In Smalltalk, a
String is a
flatCollect: method on a
String flattens the
Character instances into a
Collection. I convert the characters to a
asBag so I can use the
occurrencesOf: method to test the count of each character.
Detect / DetectIfNone
detect:ifNone: can be used to find the first object that matches a condition. The
detect: method takes a one-argument block that returns a
detect:ifNone: method additionally takes a second zero-argument block as a second parameter that is evaluated and the result returned in the case that no element matches the condition of the first block.
inject:into: injects an initial value into an iteration over a
Collection, and some result of each iteration is injected into the next iteration and so on and so forth. This method is usually used to implement methods like
max, etc. The method
inject:into: is one of the most general, flexible and powerful of the iteration patterns in Smalltalk. In the following example, I inject an empty
String into a iteration, and the result of each iteration is a concatenation of the injected
String with a comma and each element. The only element that is not concatenated with a comma is the first one.
groupedBy: iterates over a
Collection and groups the elements in a
Dictionary containing collections of the same type where the keys are derived by applying a function to each element. The
groupedBy: method takes a one-argument block that returns any type (aka
AnySatisfy / AllSatisfy / NoneSatisfy
noneSatisfy: test a collection to see if a certain condition is met and returns a
Boolean result. All three methods take a one-argument block as a parameter. The block returns a
Predicate). Each of these methods will short-circuit if the
Boolean result of the
Predicate is the opposite of what is expected for the method.
count: returns the count of the number of elements that match a given condition. The
count: method takes a one-argument block that returns a
Here’s a link to a gist with the source code in the examples above. Enjoy!
That’s all folks!
Thank you for reading! I hope you enjoyed my trip down Smalltalk memory lane. If you’re bored this holiday season with everything getting locked down due to the pandemic, then maybe give yourself the gift of a little Smalltalk learning. The syntax will be different than what you are used to, but if you learn it, you will understand why Smalltalk developers prefer it to curly brace and parentheses languages.
I hope you have a safe, happy and healthy holiday! Hug your loved ones, take care of your family and yourself.
I am a Project Lead and Committer for the Eclipse Collections OSS project at the Eclipse Foundation. Eclipse Collections is open for contributions. If you like the library, you can let us know by starring it on GitHub.