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.
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
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"
(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)
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 b | a := 1. b := 2. (a > 0) xor: (b < 0)This example returns a value true.
boolean notFollowing is an example:
(5 > 1) not "The return result is false."
5 > 1 nothas 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).
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]. ^newValueThis example sets the variable newValue equal to the greater of x or y, in this case y, and returns the value in newValue.
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]. ^xThe return result is 5.
[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
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]. ^xAnother example:
"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]. ^xthis 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.