Many people call Smalltalk a strange little language. It’s not strange, it’s different. Anything that is different requires familiarization.

Let’s look at some languages that are different in several categories…

Control Structures — the Conditional Statement

/* In C and C++, the brace brackets style of syntax has spread to

many other languages like Java, JavaScript, PHP, Perl, etc. */

if (x < y) {

x++;

printf("x is %i

", x);

}

else

printf("*** warning

"); """ In Python, whitespace indentation is part of the syntax used to delineate blocks of code. Now, that is strange! """

if x < y:

x += 1

print 'x is', x

else:

print '*** warning' =begin

In Ruby, there are no brackets for delineating blocks of code!

=end

if x < y then

x += 1

puts "x is #{x}"

else

puts "*** warning"

end "In Smalltalk, nearly all syntax is based on message passing.

The message ifTrue:ifFalse: is sent to Boolean objects."

x < y ifTrue: [ x := x + 1.

Transcript show: 'x is ',x printString; cr ]

ifFalse: [ Transcript show: '*** warning' ].

Control Structures — the Iterative Statement

// In C++, the for loop is quite strange-looking. */

for (int i = 10; i <= 200; i += 5) {

z += i;

printf("i is %i

", i);

} # In Python, the for loop departs from the C style.

# The given endpoint of range() is never part of the generated list

# which forces an inconvenience.

for i in range(10, 205, 5):

z += i

print 'i is', i # In Ruby, the for loop looks even more weird.

(10..200).step(5) do | i |

z += i

puts "i is #{i}"

end "In Smalltalk, the for loop is quite readable."

(10 to: 200 by: 5) do: [ :i |

z := z + i.

Transcript show: 'i is ',i printString;cr ].

Control Structures — the Selection Statement

/* In C++, the switch statement is rather odd-looking. */

switch (ch) {

case 'A':

count += 1;

break;

case 'a':

count -= 1;

break;

default:

printf( "count is %i

", count);

} # In Ruby, a case expression is used.

case ch

when ?A

count += 1

when ?a

count -= 1

else

puts "count is #{count}"

end

Like Python, Smalltalk doesn’t have a built-in selection statement. But it can be easily emulated. For example, I like using a dictionary for this purpose.

| test |

test := {

$A -> [ count := count + 1 ].

$a -> [ count := count - 1 ].

#default -> [ Transcript show: 'count is ',

count printString;cr ]

} asDictionary.

Then to perform the selection:

(test at: ch ifAbsent: [ test at: #default ]) value. "If there's no default case, it looks even simpler."

(test at: ch) value.

The beauty of this is that it’s also an expression that can return a value, something you don’t find in most other languages. Alternatively, you could create a class for simulating a switch, using cascading method invocations:

Object subclass: #Switch

instanceVariables: 'key found'

classVariables: ''

package: 'MyApp' Switch>>case: val do: aBlock

key = val ifTrue: [ found := true.

aBlock value ] Switch>>default: aBlock

found ifFalse: aBlock Switch>>on: test

key := test.

found := false

Then to perform the selection:

Switch new on: ch;

case: $A do: [ count := count + 1 ];

case: $a do: [ count := count - 1 ];

default: [ Transcript show: 'count is ',count printString;cr ].

This bears a striking resemblance to the C++ switch statement!

Arithmetic Operator Precedence

In Smalltalk, all messages are processed in a left-to-right order. This applies to arithmetic expressions, as well. So, for example, the expression 3 + 5 * 2 evaluates to 16, not the conventional expectation of 13. To adhere to mathematical convention, you must place parentheses around 5 * 2 to force its evaluation first, thusly:

3 + (5 * 2)

This looks a little strange but it’s not nearly as bad as in some other languages such as:

\ In Forth

5 2 * 3 + ; In Lisp

(+ 3 (* 5 2)) NB. In APL-derived J language, operators are performed in a

NB. right-to-left order! The following yields 25, not 13:

5 * 2 + 3

NB. Again, you need to place parentheses around 5 * 2.

OOP Paradigm

Smalltalk is the archetype for modern OOP languages. It is so good that Smalltalk directly influenced the design of nearly every other OOP language in use today. Frankly, no other language does OOP as well. Smalltalk is OOP done right.

If you’ve had a bad experience with OOP, then you weren’t using Smalltalk. You were probably using Java or C# or C++ or Python. It doesn’t help that some of these languages obfuscate OOP with nonsense like access modifiers (eg, public, private, protected, virtual).

Built-in Graphical IDE

Smalltalk stands alone in the pantheon of programming languages by having a built-in, graphical IDE that supports live coding. It’s also image-based, a concept shared by OS virtualization software like VMware and VirtualBox. The IDE is the principal reason Smalltalk is so incredibly productive. Read Smalltalk’s Proven Productivity.

Jobs, Jobs, Jobs

The availability of jobs for Smalltalk is its Achilles’ Heel. But the same applies to most other programming languages. Let’s look at job numbers from Indeed.com (updated April 12, 2018) for the entire United States:

Java — 67,468 Python — 55,091 JavaScript — 46,895 C++ — 34,706 C# — 28,108 Ruby — 19,095 Perl — 15,640 PHP — 11,356 Swift — 6,269 Scala — 6,165 Objective-C — 3,652 Golang — 1,345 Cobol — 1,312 Rust —810 Fortran — 714 Kotlin — 702 Clojure — 492 Julia — 439 Lua — 430 Haskell —420 Elixir —326 Erlang — 220 Lisp — 179 F# — 144 Smalltalk — 29

Job prospects don’t look rosy for Rust, Kotlin, Clojure, Julia, Haskell, and Elixir against which the top 10 languages have 7–200X the number of jobs. Job opportunities are still infinitesimal. If I care about jobs, I’d even choose Perl and PHP over these!

It’s worth noting that Objective-C bears a strong resemblance to Smalltalk, so Smalltalk experience should be applicable to Apple programming.

Conclusion

When you understand what Smalltalk is about (message passing and left associativity, image concept, live coding), the language isn’t that strange, after all. It has more in common with the major languages than differences.

Try Smalltalk (Pharo) today.