4.5: Block Syntax
- Page ID
- 39588
Blocks (lexical closures) provide a mechanism to defer the execution of expressions. A block is essentially an anonymous function with a definition context. A block is executed by sending it the message value
. The block answers the value of the last expression in its body, unless there is an explicit return (with ^) in which case it returns the value of the returned expression.
[ 1 + 2 ] value >>> 3
[ 3 = 3 ifTrue: [ ^ 33 ]. 44 ] value >>> 33
Blocks may take parameters, each of which is declared with a leading colon. A vertical bar separates the parameter declaration(s) from the body of the block. To evaluate a block with one parameter, you must send it the message value: with one argument. A two-parameter block must be sent value:value:
, and so on, up to 4 arguments.
[ :x | 1 + x ] value: 2 >>> 3 [ :x :y | x + y ] value: 1 value: 2 >>> 3
If you have a block with more than four parameters, you must use valueWithArguments:
and pass the arguments in an array. (A block with a large number of parameters is often a sign of a design problem.)
Blocks may also declare local variables, which are surrounded by vertical bars, just like local variable declarations in a method. Locals are declared after any arguments:
[ :x :y | |z| z := x + y. z ] value: 1 value: 2 >>> 3
Blocks are actually lexical closures, since they can refer to variables of the surrounding environment. The following block refers to the variable x
of its enclosing environment:
|x| x := 1. [ :y | x + y ] value: 2 >>> 3
Blocks are instances of the class BlockClosure
. This means that they are objects, so they can be assigned to variables and passed as arguments just like any other object.