View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide
Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007

Smalltalk vs. Java - Charmant Kai Tan

Understanding the differences between Java and Smalltalk.

So you've been programming in Java for the last semester or two, and finally have come comfortable in programming in such a language.
Now you begin to take CS2340, and experience a whole new language. The key to understanding any new language is its differeneces amongst
its counterparts. Without the basics, people are not able to do anything. Any skill requires a basic understanding how things work in order to accomplish greater goals. The key to understanding Smalltalk is knowing the differences from Java.

So let's start with the basics of understanding the differences between Java and Smalltalk.

Smalltalk itself is a pure object oriented language. As in other object-oriented languages, the central concept in Smalltalk is that of an object. An object is always an instance of a class. Classes are "blueprints" that describe the properties and behavior of their instances. For example, a Window class would declare that windows have properties such as the label, the position and whether the window is visible or not. The class would also declare that instances support operations such as opening, closing, moving and hiding. Each particular Window object would have its own values of those properties, and each of them would be able to perform operations defined by its class.

A Smalltalk object can do exactly three things:

1. Hold state (references to other objects).
2. Receive a message from itself or another object.
3. In the course of processing a message, send messages to itself or another object.

The state an object holds is always private to that object. Other objects can query or change that state only by sending requests (messages) to the object to do so. Any message can be sent to any object: when a message is received, the receiver determines whether that message is appropriate. (Alan Kay has commented that despite the attention given to objects, messaging is the most important concept in Smalltalk.)

Smalltalk is a 'pure' OO language, meaning that, unlike Java and C++, there is no difference between values which are objects and values which are primitive types. In Smalltalk, primitive values such as integers, booleans and characters are also objects, in the sense that they are instances of corresponding classes, and operations on them are invoked by sending messages. A programmer can change the classes that implement primitive values, so that new behavior can be defined for their instances–for example, to implement new control structures–or even so that their existing behavior will be changed. This fact is summarised in the commonly heard phrase "In Smalltalk everything is an object" (which would more accurately be expressed as "all values are objects", as variables aren't).

Since all values are objects, classes themselves are also objects. Each class is an instance of the metaclass of that class. Metaclasses in turn are also objects, and are all instances of a class called Metaclass. Code blocks are also objects.

Now let's compare the differences amongst Java and Smalltalk with basic syntax.

End of line
End of command -
Smalltalk - Period
Java - Semicolon

Comments
Smallktalk - "Comment"
Java - // Comment
/asterik symbol Comment asterik symbol/

Variable Declaration
Smallktalk - | a b c d |
Java -int a, b, c, d;

Printing
Smallktalk - Transcript show: 'Text'.
Java -System.out.println("Text");

Printing - variables
Smallktalk - Transcript show: (a) printString.
Java -System.out.println(a);

Printing - newline
Smallktalk - Transcript show: 'Text'; cr.
Java -System.out.println("Text");
(Automatic with println)

Running
Smallktalk - Select Text, left-click, 'do it'
Java -java file

Assignment
Smallktalk - a := 4
a _ 4 (will become )
Java -a = 4

Equality
Smallktalk - a = b (single "=")
Java -a == b (double "= =")

Block Delineators
Smallktalk - Brackets - [ code ]
Java -Curly Braces - { code }

Object Creation
Smallktalk - obj := Object new
obj := Object initialize
obj := Object new initialize
Java -obj = new Object()

Function - Usage/Call
Smallktalk - Method: value
Java -Function(value)






Other Basics in Smalltalk:

No need to compile - is an interpreted languageNo need for libraries - everything is already there
All methods are "virtual" - decided at run-time Everything is an object - contained in some class
Smalltalk has no pointers - or, alternatively, everything is a pointerVariables don't have real types - no int, float, etc. (Do have String, Integer, Float, etc. classes)
Our variables point to objects of this type - are not that type
So this is totally legal and gives the following output:

a := 'Hello'.
Transcript show: a; cr.
a := 4.
Transcript show: (a) printString.

Hello
4

Assignment is :=, test for equality is = Comments are in double quotes, strings are in single quotes
As with C/C++ and Java, Squeak is case sensitive

Conditionals
These are done a little differently in Squeak. Although they could've been shown in the table above, I feel a little more explanantion is needed for them. I'll look at them in terms of usage. As in C/C++ and Java, these execute using code in blocks. Don't forget to put these inside brackets - []. And as in these other languages, you can have multiple statements in a block. Unlike with C/C++ and Java, you need to put a period after the braces when a block closes. Smalltalk treats a block as a statement.

While
A while loop from C/C++ would be done in the following way, using Smalltalk (there is also a "whileFalse:" construct) :

x := 0.
[ (x 10) ]
whileTrue: [Transcript show: (x) printString.
Transcript show: ' '.
x := x + 1.].


0 1 2 3 4 5 6 7 8 9

As with other languages, you can build pretty much any other conditionals out of while loops and some combination of other code.

If/Else
There is a relatively easy way to do this as well. The important functions here are called ifTrue and ifFalse. They can be used separately or together to form an if/else block. If used together, put a period after the second block, but not the first one (notice in example below):

a := 0.
(a = 0)
ifTrue: [Transcript show: 'A is True'; cr.].

b := 0.
(b > 0)
ifFalse: [Transcript show: 'B is false'; cr.].

(a = b)
ifTrue: [Transcript show: 'A and B are equal'; cr.]
ifFalse: [Transcript show: 'A and B are NOT equal'; cr.].


A is True
B is false
A and B are equal

For
Squeak has a cool way of working with this called to:by:do:

1 to: 10 by: 2 do: [:x | Transcript show: 'Hello '.].


Hello Hello Hello Hello Hello

Notice the ":x" in the block. This keeps track of the variable and the value for it. In some cases, you may want to know what this value is:

1 to: 10 by: 2 do: [:x | Transcript show: (x) printString.
Transcript show: ' '.].


1 3 5 7 9

You can also get rid of the by: and just do to:do: like this

1 to: 10 do: [:x | Transcript show: 'Hello '.].


Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello

If you know exactly how many times you want to do something, then you can do that as well:

10 timesRepeat: [Transcript show: 'Hello '.].


Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello


More Examples
The following examples illustrate the most common objects which can be written as literal values in Smalltalk-80 methods.

Numbers. The following list illustrates some of the possibilities.

42
123.45
1.2345e2
2r10010010
16rA000

The last two entries are a binary and a hexadecimal number, respectively. The number before the 'r' is the radix or base. The base does not have to be a power of two; for example 36rSMALLTALK is a valid number (for the curious, equal to 80738163270632 decimal).

Characters are written by preceding them with a dollar sign:

$A

Strings are sequences of characters enclosed in single quotes:

'Hello, world!'

To include a quote in a string, escape it using a second quote:

'I said, ''Hello, world!'' to them.'

Double quotes do not need escaping, since single quotes delimit a string:

'I said, "Hello, world!" to them.'

Two equal strings (strings are equal if they contain all the same characters) can be different objects residing in different places in memory. In addition to strings, Smalltalk has a class of character sequence objects called Symbol. Symbols are guaranteed to be unique–there can be no two equal symbols which are different objects. Because of that, symbols are very cheap to compare and are often used for language artifacts such as message selectors (see below).

Symbols are written as # followed by characters. For example:

  1. foo

Arrays:

  1. (1 2 3 4)

defines an array of four integers.

And last but not least, blocks (anonymous function literals)

[... Some smalltalk code...]

Blocks are explained in detail further in the text.

Many Smalltalk dialects implement additional syntaxes for other objects, but the ones above are the bread and butter supported by all.

[edit] Variable declarations

The two kinds of variable commonly used in Smalltalk are instance variables and temporary variables. Other variables and related terminology depend on the particular implementation. For example, VisualWorks has class shared variables and namespace shared variables, while Squeak and many other implementations have class variables, pool variables and global variables.

Temporary variable declarations in Smalltalk are variables declared inside a method (see below). They are declared at the top of the method as names separated by spaces and enclosed by vertical bars. For example:

index

declares a temporary variable named index. Multiple variables may be declared within one set of bars:

index vowels

declares two variables: index and vowels.

[edit] Assignment

A variable is assigned a value via the ':=' syntax. So:

vowels := 'aeiou'

Assigns the string 'aeiou' to the previously declared vowels variable. The string is an object (a sequence of characters between single quotes is the syntax for literal strings), created by the compiler at compile time.

In the original Parc Place image, the glyph of the underscore character (_) appeared as a left-facing arrow. Smalltalk originally accepted this left-arrow as the only assignment operator. Some modern code still contains what appear to be underscores acting as assignments, harking back to this original usage. Most modern Smalltalk implementations accept either the underscore or the colon-equals syntax.

[edit] Messages

The message is the most fundamental language construct in Smalltalk. Even control structures are implemented as message sends. Smalltalk adopts by default a synchronous, single dynamic message dispatch strategy (as contrasted to a synchronous, multiple dispatch strategy adopted by some other object-oriented languages).

The following example sends the message 'factorial' to number 42:

42 factorial

In this situation 42 is called the message receiver, while 'factorial' is the message selector. The receiver responds to the message by returning a value (presumably in this case a factorial of 42). Among other things, the result of the message can be assigned to a variable:

aRatherBigNumber := 42 factorial

"factorial" above is what is called a unary message because only one object, the receiver, is involved. Messages can carry additional objects as arguments, as follows:

2 raisedTo: 4

In this expression two objects are involved: 2 as the receiver and 4 as the message argument. The message result, or in Smalltalk parlance, the answer is supposed to be 16. Such messages are called keyword messages. A message can have more arguments, using the following syntax:

'hello world' indexOf: $o startingAt: 6

which answers the index of character 'o' in the receiver string, starting the search from index 6. The selector of this message is "indexOf:startingAt:", consisting of two pieces, or keywords.

Such interleaving of keywords and arguments greatly improves readability of code, since arguments are explained by their preceding keywords. For example, an expression to create a rectangle using a C++ or Java-like syntax might be written as:

new Rectangle(100, 200);

It's unclear which argument is which—is the argument order (width, height) or (height, width)? In Java, you have to look up the API online to find out that the class's argument-order is, in fact, (width, height). By contrast, in Smalltalk, this code would be written unambiguously as:

Rectangle width: 100 height: 200

The receiver in this case is "Rectangle", a class, and the answer will be a new instance of the class with the specified width and height.

Finally, most of the special (non-alphabetic) characters can be used as what are called binary messages. These allow mathematical and logical operators to be written in their traditional form:

3 + 4

which sends the message "+" to the receiver 3 with 4 passed as the argument (the answer of which will be 7). Similarly,

3 > 4

is the message ">" sent to 3 with argument 4 (the answer of which will be false).

Notice, that the Smalltalk-80 language itself does not imply the meaning of those operators. The outcome of the above is only defined by how the receiver of the message (in this case a Number instance) responds to messages "+" and ">".

A side effect of this mechanism is operator overloading. A message ">" can also be understood by other objects, allowing the use of expressions of the form "a > b" to compare them.

[edit] Expressions

An expression can include multiple message sends. In this case expressions are parsed according to a simple order of precedence. Unary messages have the highest precedence, followed by binary messages, followed by keyword messages. For example:

3 factorial + 4 factorial between: 10 and: 100

is evaluated as follows:

1. 3 receives the message "factorial" and answers 6
2. 4 receives the message "factorial" and answers 24
3. 6 receives the message "+" with 24 as the argument and answers 30
4. 30 receives the message "between:and:" with 10 and 100 as arguments and answers true

The answer of the last message send is the result of the entire expression.

Parentheses can alter the order of evaluation when needed. For example,

(3 factorial + 4) factorial between: 10 and: 100

will change the meaning so that the expression first computes "3 factorial + 4" yielding 10. That 10 then receives the second "factorial" message, yielding 3628800. 3628800 then receives "between:and:", answering false.

Note that because the meaning of binary messages is not hardwired into Smalltalk-80 syntax, all of them are considered to have equal precedence and are evaluated simply from left to right. Because of this, the meaning of Smalltalk expressions using binary messages can be different from their "traditional" interpretation:

3 + 4 5

is evaluated as "(3 + 4) 5", producing 35.

Unary messages can be chained by writing them one after another:

3 factorial factorial log

which sends "factorial" to 3, then "factorial" to the result (6), then "log" to the result (720), producing the result 2.85733.

A series of expressions can be written as in the following (hypothetical) example, each ending with a period. This example first creates a new instance of class Window, stores it in a variable, and then sends two messages to it.

| window |
window := Window new.
window label: 'Hello'.
window open.

If a series of messages are sent to the same receiver as in the example above, they can also be written as a cascade with individual messages separated by semicolons:

(Window new)
label: 'Hello';
open

This rewrite of the earlier example as a single expression avoids the need to store the new window in a temporary variable. According to the usual precedence rules, the unary message "new" is sent first, and then "label:" and "open" are sent to the answer of "new".

[edit] Code blocks

A block of code (an anonymous function) can be expressed as a literal value (which is an object, since all values are objects.) This is achieved with square brackets:

[ :params | ]

Where :params is the list of parameters the code can take. This means that the Smalltalk code:

[:x | x + 1]

can be understood as:

f(x) = x + 1

(or, expressed using lambda calculus):

λx.(x+1)

and

[:x | x + 1] value: 3

can be evaluated as

f(3) = 3 + 1

The resulting block object is a closure. It can (at any time) access the variables of its enclosing lexical scopes. Blocks are first class objects. That is, references to blocks can be passed as arguments, returned as values, or stored as a state, just like any other objects. Blocks can be asked to execute their code by sending them a "value"-message (with one argument for each parameter in the block).

The literal representation of blocks was an innovation which allowed certain code to be significantly more readable; it allowed algorithms involving iteration to be coded in a clear and concise way. Code that would typically be written with loops in some languages can be written concisely in Smalltalk using blocks, sometimes in a single line.

positiveAmounts := allAmounts select: [:amt | amt isPositive]

Note that this is related to functional programming, wherein patterns of computation (here selection) are abstracted into higher-order functions. For example, the message select: on a Collection is equivalent to the higher-order function filter on an appropriate functor.

[edit] Control structures

Control structures do not have special syntax in Smalltalk. They are instead implemented as messages sent to objects. For example, conditional execution is implemented by sending the message ifTrue: to a Boolean object, passing as an argument the block of code to be executed if and only if the Boolean receiver is true.

The following code demonstrates this:

result := a > b
ifTrue:[ 'greater' ]
ifFalse:[ 'less' ]

Blocks are also used to implement user-defined control structures, enumerators, visitors, pluggable behavior and many other patterns. For example:

aString vowels
aString := 'This is a string'.
vowels := aString select: [:aCharacter | aCharacter isVowel].

In the last line, the string is sent the message select: with an argument that is a code block literal. The code block literal will be used as a predicate function that should answer true if and only if an element of the String should be included in the Collection of characters that satisfy the test represented by the code block that is the argument to the "select:" message.

A String object responds to the "select:" message by iterating through its members (by sending itself the message "do:"), evaluating the selection block ("aBlock") once with each character it contains as the argument. When evaluated (by being sent the message "value: each"), the selection block (referenced by the parameter "aBlock", and defined by the block literal "[:aCharacter | aCharacter isVowel]"), answers a boolean, which is then sent "ifTrue:". If the boolean is the object true, the character is added to a string to be returned. Because the "select:" method is defined in the abstract class Collection, it can also be used like this:

rectangles aPoint
rectangles := OrderedCollection
with: (Rectangle left: 0 right: 10 top: 100 bottom: 200)
with: (Rectangle left: 10 right: 10 top: 110 bottom: 210).
aPoint := Point x: 20 y: 20.
collisions := rectangles select: [:aRect | aRect containsPoint: aPoint].

[edit] Classes

This is a stock class definition:

Object subclass: #MessagePublisher
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Smalltalk Examples'

Often, most of this definition will be filled in by the environment. Notice that this is actually a message to the "Object"-class to create a subclass called "MessagePublisher". In other words: classes are first-class objects in Smalltalk which can receive messages just like any other object and can be created dynamically at execution time.

[edit] Methods

When an object receives a message, a method matching the message name is invoked. The following code defines a method publish, and so defines what will happen when this object receives the 'publish' message.

publish
Transcript show: 'Hello, World!'

The following method demonstrates receiving multiple arguments and returning a value:

quadMultiply: i1 and: i2
"This method multiplies the given numbers by each other and the result by 4."
| mul |
mul := i1 i2.
^mul 4

The method's name is #quadMultiply:and:. The documentation is represented by a string, making it accessible from the program. Return value is specified with the ^ operator.

Note that objects are responsible for determining dynamically at runtime which method to execute in response to a message–while in many languages this may be (sometimes, or even always) determined statically at compile time.

[edit] Instantiating classes

The following code:

MessagePublisher new

creates (and returns) a new instance of the MessagePublisher class. This is typically assigned to a variable:

publisher := MessagePublisher new

However, it is also possible to send a message to a temporary, anonymous object:

MessagePublisher new publish

[edit] Hello World example

Main article: Hello world program

In the following code, the message "show:" is sent to the object "Transcript" with the String literal 'Hello, world!' as its argument. Invocation of the "show:" method causes the characters of its argument (the String literal 'Hello, world!') to be displayed in the transcript ("terminal") window.

Transcript show: 'Hello, world!'.

Note that a Transcript window would need to be open in order to see the results of this example.



I hope this helps the new Smalltalk programmer have a better understanding of Smalltalk and learning the basics is key to succeeding!

Links to this Page