How does Smalltalk deal with data, logical comparisons, loop and other conditional functions? In the previous chapter, Smalltalk statement were discussed. This chapter concentrates on how Smalltalk implements data and operations on data. As mentioned before that everything in Smalltalk is an object. Hence, Smalltalk implements all data types as Smalltalk classes and operations on data as methods in these classes.
Unlike procedural languages where data types and operations are defined as part of the language syntax, Smalltalk has no awareness of data types or data operations. New data can be created like creating new instance of a class. Operations can be perform on data by sending a message to the object.
Smalltalk provides support for literals as instances of five classes: String, Number, Character, Symbol and Array. The subclass of Number: Integer, Float, and Fraction are part of the literals too.
A number can be one of the following:
123 "an integer" -234 "an negative interger" 3/4 "a fraction" -1/7 "an negative fraction" 4.564 "a floating point" -2.34e10 "an negative floating point" .23 "AN ERROR! Cannot begin with decimal point" 59. "AN ERROR! Cannot end with decimal point" 2.4e.7 "AN ERROR! Exponent must be an integer"
aString first = $Y
`This is a string.' `Strings may contain this %@#^|\' newStudent name: `Steve' "set the argument on name: message to a string."
#name "an identifier" #+ "a binary selector" #at:put: "a keyword selector"
#(`one' `two' `three' `four') "Produces an array with four strings" #(1 2 3 4) "Produces an array with four integers" #(1 `two' $Y) "Produces an array with an integer, a string, and a character"
number operation numberwhere an operation can be one of the following:
+ "addition" - "subtraction" * "multiplication" / "division" // "division with truncation" \\ "remainder from division"Some examples of arithmetic operations are follows:
3 + 4. "returns 7" 9 // 4. "returns 2" 9 \\ 4. "returns 1" | x y | x := 2. y := 6. x * y "returns 12"
DummyVariable := nil.
Nil also can be used as the return value in a method to indicate that an operation is not successful. For example, the following logic returns nil if an argument is not positive, otherwise it returns the result of the arithmetic operation:
raise: aNumber toPower: aPower "Raise aNumber to the power specified by aPower. Return nil if aPower is not positive. Otherwise, return the result." aPower < 0 ifFalse: [^nil]. ^aNumber raisedTo: aPower
A comparison statement has the following format:
value comparison valuewhere value can be any expression that results in a value that can be compared, such as numbers, strings, characters, and symbols, and comparison can be any valid comparison operation. Some examples are:
> "greater than" < "less than" = "equal to in value" ~= "not equal in value" >= "greater than or equal to" <= "less than or equal to" == "is the same object"
Logical comparisons return a value of either true or false, which are instances of the classes True and False.
Some examples of logical comparison are follows:
3 > 8 "returns false" $e <= $f "returns true" | i j | i := 3. j := 7. i == j "returns false"
The "==" comparison, in the last example, checks to see if the two objects are the same object, rather than equal in value.
In Smalltalk, booleans expressions can be combined into one result using either the or operation or the and operation. These two functions can be performed with either binary messages or keyword messages.
The binary messages for logical and is a & and logical or is a |. For example:
(a > 0) & (b < 0) "Return true if a is positive and b is negative,Otherwise false."
(a > 0) | (b < 0) "Return true if either a is positive or b is negative."
A statement can contain an unlimited number of these binary messages. For example:
| x y z | x := 3. y := 5. z := 7. (x > 0) & (y < 0) | (x > y) & (y = z)
The keyword messages are and:, and or:. The format for these messages is:
boolean and: [code] boolean or: [code]
The boolean is any expression that results in value of true or false. The block of code enclosed in brackets (see "Blocks") must return a value of true or false. The and: and or: methods combine the two booleans and return the proper result.
There is a difference between the binary message & and | and the keyword message and: and or:, respectively. The keyword messages are considered to be short cuts because they use delayed evaluation. The code in the block is not evaluated until the boolean receiver is determined to be true or false.
In the case of the and: message, if the receiver evaluates to false, then the code in the block is never evaluated because an and operation with false is always false.
In the case of the or: message, if the receiver evaluates to true, then the code in the block is never evaluated because an or operation with true is always true.
Following is an example using keyword messages:
| x y z | x := 3. y := 5. z := 7. (((x > 0) and: [y < 0]) or: [x > y]) and: [y = z]
A boolean also supports the function of exclusive or by providing the keyword message xor:. This is identical in format to the keyword messages and: and or: except that the argument must be a boolean, not a block of code. For example:
| a b | a := 1. b := 2. (a > 0) xor: (b < 0)
This example returns a value true.
The unary message not provides the not function. This message reverses the boolean (true becomes false, or false becomes true). The format is:
Following is an example:
(5 > 1) not "The return result is false."
It is important to make sure a boolean value immediately precedes the operation of not. When unsure, enclose each expression in parentheses. It ensures that the logic happens in the correct order. For example, the expression:
5 > 1 not
has two messages: the binary message > and the unary message not. Smalltalk executes unary message first (see rule 4 of "Order of Message Execution"), which would cause the number 1 to receive the not message. That is clearly not the correct execution sequence (and would cause a runtime error).
Conditional logic allows the execution of code depending on the value of a boolean. There are several keyword messages that provide this function as follows:
boolean ifTrue: [code] ifFalse: [code].
where boolean is any expression that result in true or false. The expression [code] can be any zero-argument block.
The keyword message ifTrue:ifFalse executes a different block of code depending on the value of the boolean. For example:
| x y newValue | x := 1. y := 2. (x > y) ifTrue: [newValue := x] ifFalse: [newValue := y]. ^newValue
This example sets the variable newValue equal to the greater of x or y, in this case y, and returns the value in newValue.
Smalltalk supports four traditional types of loops. They are:
The four keyword messages that provide these functions are: timesRepeat:, whileTrue:, whileFalse:, and to:do:.
The message timesRepeat: executes a block of code a specified number of times. The format of the message is:
number timesRepeat: [code]
where number can be any expression that results in an integer, and code is a zero-argument block of code. Here is an example:
"Add 1 to the variable x three times." | x | x := 2. 3 timesRepeat: [x := x + 1]. ^x
The return result is 5.
These two messages perform the same operation except one tests for true and the other tests for false. The format of the message is:
[boolean] whileFalse: [code] [boolean] whileTrue: [code]
Boolean can be any expression that results in a value of true or false; it must be enclosed in a block. The expression [code] is a zero-argument block of code. For example, both of the following examples incrementy by 1 until it is greater than x.
"Lopp until x is less than y" | x y | x := 5. y := 0. [x < y] whileFalse: [y := y + 1]. ^y
"Loop until y is greater than x" | x y | x := 5. y := 0. [y <= x] whileTrue: [y := y + 1]. ^y
The to:do: message executes a block multiple times based on a start and stop value. The format of the message is:
number1 to: number2 do: [:var | code].
where number1 and number2 can be any expression that results in a number and [:var | code] is a one-argument block. The block executes for each number that is within the range number1 through number2, inclusive. (This form is almost always used with integers only, stepping 1 at a time.) The argument of the one-argument block equals the current value in the range.
"Execute this block 3 times with i set to each value between the range of 1 through 3. At the end x equals 6." | x | x := 0. 1 to: 3 do: [:i | x := x + i]. ^x
"Multiply x by the number 5 through 10. At the end x equals to 151,200." | x | x := 1. 5 to: 10 do: [:increment | x := x * increment]. ^x
this example executes the block if code six times (the number 5 through 10). The first time the block executes, the value of increment is 5, the next time 6, and so on, until the last time it is 10.
We have discussed the following in this chapter:
Go to Chapter 5: Classes
Return to Chapter 3: Smalltalk Statements
Return to Main Page