next up previous contents index
Next: 3.5 Magnitudes and Numbers Up: 3 The Slate World Previous: 3.3 Traits   Contents   Index

Subsections

3.4 Blocks, Booleans, and Control-Flow

3.4.1 Boolean Logic

Slate's interpreter primitively provides the objects True and False, which are clones of Boolean, and delegate to Boolean traits. Logical methods are defined on these in a very minimalistic way. Table cap:Basic-Logical-Operators shows the non-lazy logical methods and their meanings.


Table 2: Basic Logical Operators
Description Selector
AND/Conjunction /\
OR/Disjunction \/
NOT/Negation not
EQV/Equivalence eqv:
XOR/Exclusive-OR xor:


3.4.2 Basic Conditional Evaluation

Logical methods are provided which take a block as their second argument (/\, \/, and:, or:, xor:, eqv:). By accepting a block as the second argument, they can and do provide conditional evaluation of the second argument only in the case that the first does not decide the total result automatically5. Blocks that evaluate logical expressions can be used lazily in these logical expressions. For example,

(x < 3) /\ [y > 7].
only evaluates the right-hand block argument if the first argument turns out to be True.

(x < 3) \/ [y > 7].
only evaluates the right-hand block argument if the first argument turns out to be False.

In general, the basic of booleans to switch between code alternatives is to use ifTrue:, ifFalse:, and ifTrue:ifFalse: for the various combinations of binary branches. For example,

x isNegative ifTrue: [x: x negated].
ensures that x is positive by optionally executing code to make it positive if it's not. Of course if only the result is desired, instead of just the side-effect, the entire expression's result will be the result of the executed block, so that it can be embedded in further expressions.

Conditional evaluation can also be driven by whether or not a slot has been initialized, or whether a method returns Nil. There are a few options for conditionalizing on Nil:

expr ifNil: block
and expr ifNotNil: block execute their blocks based on whether the expression evaluates to Nil, and returns the result.
expr ifNil: nilBlock ifNotNil: otherBlock
provides both options in one expression.
expr ifNotNilDo: block
applies the block to the expression's result if it turns out to be non-Nil, so the block given must accept one argument. ifNil:ifNotNilDo: is also provided for completeness.


3.4.3 Looping

Slate includes various idioms for constructing basic loops.

loop
executes the block repeatedly, indefinitely.
n timesRepeat: block
executes the block n times.
condition whileTrue: block
and condition whileFalse: block execute their blocks repeatedly, checking the condition before each iteration.
whileTrue
and whileFalse execute their blocks repeatedly, checking the return value before repeating iterations.
a upTo: b do: block
and b downTo: a do: block executes the block with each number in turn from a to b, inclusive.
upTo:by:do:
and downTo:by:do: executes the block with each number in turn in the inclusive range, with the given stepping increment.
a below: b do: block
and b above: a do: block act identically to the previous method except that they stop just before the last value. This assists in iterating over array ranges, where the 0-based indexing makes a difference in range addresses by one, avoiding excessive use of size - 1 calls.
Slate's looping control structures can easily be extended without concern due to the fact that the interpreter unrolls properly tail-recursive blocks into low-level loop code that re-uses the same activation frame. So basically structuring custom looping code so that it calls itself last within its own body and returns that value will avoid the need for increasing stack space per iteration.


next up previous contents index
Next: 3.5 Magnitudes and Numbers Up: 3 The Slate World Previous: 3.3 Traits   Contents   Index
Brian Rice 2004-10-30