parent previous next question (Smalltalk Textbook 12)

Evaluation

This section discuss evaluation of message expressions. Usually you select a message expression and 'do it' via the yellow button menu, but there are other ways as well.

For example, let me show several ways to calculate 3 + 4. In an object oriented way you read '3 + 4' as "send the '+4' message to the '3' object.

-------------------------------------------------------------------
3 + 4

3 perform: #+ with: 4

3 perform: #+ withArguments: #(4)

Compiler evaluate: '3 + 4'

Compiler evaluate: '3 + 4' logged: false

Compiler evaluate: '3 + 4' for: nil logged: false

Compiler evaluate: 'self + 4' for: 3 logged: false
-------------------------------------------------------------------

All of the above statements answer '7'. You can make many other programs do the same thing by combining these programs. You have a compiler which translates programs along with a browser which supports you in writing programs in the Smalltalk programming environment. So experiment with the above statements. Now let me explain what is happening inside the Smalltalk environment when you use 'do it' on a selected message expression in the work space. First, evaluate Program 12-1.


Program-12-1: (Compiler, CompiledMethod, MethodNode; 
copmile:in:notifying:ifFail, selector, block, node, generate)
-----------------------------------------------------------
| aReceiver aClass aMethodNodeHolder aMethodNode
  aSymbol aBlockNode aCompiledMethod anObject |
aReceiver := nil.
aClass := aReceiver class. "==> UndefinedObject"
aMethodNodeHolder := Compiler new
        compile: 'doIt ^(3 + 4)'
        in: aClass
        notifying: nil
        ifFail: nil.
aMethodNode := aMethodNodeHolder node.
aSymbol := aMethodNode selector.
aBlockNode := aMethodNode block.
aCompiledMethod := aMethodNodeHolder generate.
anObject := aReceiver performMethod: aCompiledMethod.
Transcript cr; show: aSymbol printString.
Transcript cr; show: aBlockNode printString.
Transcript cr; show: anObject printString.
-----------------------------------------------------------

You should see the following statements in the Transcript.

------------------------------------------------------------
#doIt
{[^3 + 4]}
7
------------------------------------------------------------

Program 12-1 executed 'do it' to the program '3 + 4' in the workspace, then compiled it for the 'nil' class receiver. The compiler makes 'aMethodNode' from the program, then translates it to byte-code (which is machine language for the Smalltalk virtual machine) to create 'aCompiledMethod'. The Smalltalk virtual machine simulates a unified hardware machine across several platforms. The compiler stores a pair of 'aMethodNode' and 'aCompiledMethod' in 'aMethodNodeHolder'. After compiling, this program accesses 'aSymbol' (message name), 'aBlockNode' (execution procedure), 'anObject' (execution result) from 'aMethodNodeHolder' and writes these to the transcript.

To specify 'nil:' as the receiver in

	anObject := aReceiver performMethod: aCompiledMethod.

in a sense means that you, the user, are the receiver for which this method is being compiled and performed. Therefore, 'do it' '3 + 4' in the work space means to compile '3 + 4' for you as the receiver, then evaluate the result of compilation for you. Now of course you are not part of the Smalltalk environment, but the compiler always compiles things for a class and the reason you can serve as a suitable alternate is that the expression '3 + 4' contains no references to anything outside of itself. If it referenced a class instance variable, for example, then the compiler would need to resolve the name reference and thus would need to have access to the class for which an expression (method) is being compiled.

Let me describe '{[^3 + 4]}', the second statement printed on the Transcript. This is a block closure. In fact, writing a message expression in the work space is same as creating a block closure object in Smalltalk.

-----------------------------------------------
[3 + 4] value
[:argument | 3 + argument] value: 4
------------------------------------------------

The above two expressions calculate '3 + 4' in a round-a-bout way using block closures. The following two programs are equivalent, but use temporary variables to clarify what's going on.

-------------------------------------------------
| blockClosure |
blockClosure := [3 + 4].
blockClosure value

| blockClosure |
blockClosure := [:argument | 3 + argument].
blockClosure value: 4
--------------------------------------------------

Block closures are like lambda expressions in Lisp and can be used to implement lazy evaluation. Program 12-2 uses block closures to implement recursive lazy evaluation. Program 12-2 scans an array which contains nested values in depth first order, then prints values one by one on the transcript, prefixed by the nesting level of the recursive call. Each time a recursive call is made to the depthFirst block, we increment the lvl variable by one. To test your understanding, you should guess the nesting level of each element of anArray, then evaluate Program 12-2 and check your answers against the Transcript.


Program-12-2: (Array; recursion, depth first, search, block closure)
-----------------------------------------------------------------
| anArray depthFirst transcriptOutput prefix|
prefix := ''.
anArray := #(1 #(2 3 #(4 #(5 6 ) 7 ) 8 ) #(9 #(10 11 12 ) ) ).
depthFirst :=
        [:array :block :lvl|
        array do: [:each |
                each isImmediate
                        ifTrue: [
			prefix := ''.
			lvl timesRepeat: [prefix := prefix, '    '].
			block value: 
			(prefix, lvl printString, ': ', each printString)]
                        ifFalse: [depthFirst value: each
				value: block
				value: lvl + 1]]].
transcriptOutput := [:that | Transcript cr; show: that].
Transcript cr; cr; show: 'Nesting level:  Item'.
depthFirst value: anArray value: transcriptOutput value: 1
-----------------------------------------------------------------

Block closures provide an amazing amount of freedom and power in Smalltalk.


parent previous next question
Copyright (C) 1994-1996 by Atsushi Aoki
Translated by Kaoru Rin Hayashi & Brent N. Reeves