Chapter 4: Data Operations


Return to [ Table of Contents] [ Main Page] [ Previous Chapter] [ Next Chapter]

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.

Literals

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.

Number

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" 

Character

A character is any ASCII character preceded by a $ sign, such as $G or $@. The following statement checks to whether the first character of a string is equal to a capital Y:

      aString first = $Y

String

A string is any sequence of characters enclosed between single quotes. For example:

      `This is a string.'
      `Strings may contain this %@#^|\'

       newStudent name: `Steve'       "set the argument on name: 
                                       message to a string."

Symbol

A symbol is an identifier, binary selector, or keyword selector preceded by a pound sign, #. All symbols are unique.

      #name          "an identifier"
      #+             "a binary selector"
      #at:put:       "a keyword selector"

Array

An array is a data structure whose elements can be any valid object. An array literal is an indexed sequence of literals. A number, or pound sign (#) precedes this sequence and parentheses enclosed the sequence. For example:

      #(`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" 


Arithmetic Operations

An arithmetic operation statement for Smalltalk has the following form:
      number operation number
where 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"


Concept of Nil

In Smalltalk, nil is an object which means "nothing". All variables initially are point to nil. Any variable can be set to nil during execution with a statement that look like this:

      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


Logical Comparisons

A comparison statement has the following format:

      value comparison value
where 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.

Logical "and" and Logical "or"

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.

Binary 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)

Keyword Messages

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]

Exclusive Or

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.

Not

The unary message not provides the not function. This message reverses the boolean (true becomes false, or false becomes true). The format is:

      boolean not

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

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.


Looping

Smalltalk supports four traditional types of loops. They are:

The four keyword messages that provide these functions are: timesRepeat:, whileTrue:, whileFalse:, and to:do:.

timesRepeat:

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.

whileTrue: and whileFalse:

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

to:do:

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    

Another 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].
      ^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.


Summary

We have discussed the following in this chapter:

Return to [Top of the page]
Smalltalk Tutorial

Go to Chapter 5: Classes

Return to Chapter 3: Smalltalk Statements

Return to Main Page