Vision Class: Boolean
Overview
The class Boolean provides the protocol for logical values. Logical value are represented by the two subclasses of Boolean - TRUE and FALSE. Most of the protocol for booleans is actually implemented at these subclasses.
The Boolean class is a direct subclass of Object:
Object | Boolean | |-- FALSE | |-- TRUE
Generating Boolean Values
The messages TRUE and FALSE are defined at the class Object to return the objects representing the two Boolean values. You can assign these values to variables and properties using the standard procedures. For example:
!trueValue <- TRUE ; Currency defineFixedProperty: 'status' ; Named Currency USD :status <- FALSE ;
Many messages return one of these values. The relational messages =, ==, !=, !==, <, <=, >, >= return a TRUE or FALSE value when used to compare two objects of the same class. For example:
3 < 4returns the object TRUE and:
"3" > "4"returns the object FALSE.
Whenever a new class is created, the message isXXX (where XXX is the class name) is defined as a class constant for the new class and for Object. The value of the constant for the new class is TRUE and the value for the Object class is FALSE. These messages are automatically defined when you create new classes using the createSubclass: message. For example, when you create a new class TestClass using:
Object createSubclass: "TestClass" ;the message isTestClass is automatically defined using:
TestClass define: 'isTestClass' toBe: TRUE ; Object define: 'isTestClass' toBe: FALSE ;The expression:
TestClass isTestClassreturns TRUE since this object is an instance of TestClass. The expression:
3 isTestClassreturns FALSE since the integer object will use the implementation of isTestClass defined at Object.
Many other messages have been defined to return a Boolean value including:
Message | Class | Definition | Sample |
isBlank | String | Is recipient blank? | " abc" isBlank |
contains: | String | Does recipient contain parameter as a substring? | "whatAmI" contains: "^what" . |
all: | Collection | Do all members of recipient respond to parameter with TRUE ? | 5 sequence all: [ isNumber ] . |
any: | Collection | Do any members of recipient respond to parameter with TRUE? | 5 sequence any: [ ^self < 3 ] . |
between:and: | Number | Is recipient value between two parameter values? | 5 between: 3 and: 7 . |
within:percentOf: | Number | Is recipient value within parameter1 percent of parameter2? | 100 within: 10 percentOf: 105 . |
isDefault | Object | Is recipient the default instance for its class? | Named Currency Default isDefault |
Logical Messages
The binary message && is defined for the Boolean classes to perform a logical "and" between the recipient Boolean and the parameter. The binary message || is defined for the Boolean classes to perform a logical "or" between the recipient Boolean and the parameter. The parameter can be supplied as a Boolean value or as a block that evaluates to a Boolean value.
The following rules apply:
Expression | Returns | Sample |
TRUE && TRUE | TRUE | 3 < 4 && 4 < 5 |
TRUE && FALSE | FALSE | 3 < 4 && 4 > 5 |
FALSE && TRUE | FALSE | 3 > 4 && 4 < 5 |
FALSE && FALSE | FALSE | 3 > 4 && 4 > 5 |
TRUE || TRUE | TRUE | 3 < 4 || 4 < 5 |
TRUE || FALSE | TRUE | 3 < 4 || 4 > 5 |
FALSE || TRUE | TRUE | 3 > 4 || 4 < 5 |
FALSE || FALSE | FALSE | 3 > 4 || 4 > 5 |
If you supply the parameter to these messages as a block, it is only evaluated if needed. Since && returns FALSE if the recipient object is FALSE independent of the parameter, the block only needs to be evaluated if the recipient is TRUE. Likewise, the || message returns TRUE if the recipient object is TRUE independent of the parameter. If you do not supply the parameter as a block, it is evaluated prior to being passed to the message. For example:
!object <- 3 ; object isString && object count < 5generates the Selector 'count' Not Found error since the message count is being sent to a numeric object. If you supply this parameter as a block:
!object <- 3 ; object isString && [ object count < 5 ]the value FALSE is returned (since object is not a string) and no error message is generated.
The message not is defined for the Boolean classes to return TRUE when sent to FALSE and to return FALSE when sent to TRUE. For example:
( 3 < 4 ) notreturns FALSE.
Conditional Messages
Several messages that perform conditional tests can be sent to the Boolean values:
The first three of these messages can only be sent to the Boolean objects. The last three can be sent to any object and evaluate their "true clause" when sent to TRUE and their "false clause" when sent to FALSE.
The ifTrue: message evaluates its block parameter if the recipient is TRUE and returns the result of evaluating the block. If the recipient is FALSE, the NA value is returned. The ifFalse: message evaluates its block parameter if the recipient is FALSE and returns the result of evaluating the block. If the recipient is TRUE, the NA value is returned. The ifTrue:ifFalse: message evaluates its first block parameter if the recipient is TRUE and evaluates its second block parameter if the recipient is FALSE. The result of the block evaluation is returned. For example:
!result <- 3 > 2 ifTrue: [ " this is true" print ; 100 ] ;Since the expression 3 > 2 evaluates to TRUE, the block is evaluated. The string "this is true" is displayed and the variable result is set to 100, the value returned by the block. In the expression:
!result <- 3 > 4 ifTrue: [ " this is true" print ; 100 ] ;the block is not evaluated, since the expression 3 > 4 evaluates to FALSE. In this case the variable result is set to NA, the value returned by the ifTrue: message when the block is not evaluated.
The message ifTrue:ifFalse: allows you to supply different blocks for the two cases. For example:
!result <- Currency instanceList count > 100 ifTrue: [ "Many Currencies" printNL; 100 ] ifFalse: [ "Few Currencies" printNL ; 1 ] ;If the expression Currency instanceList count > 100 evaluates to TRUE, the first block is evaluated. The string "Many Currencies" is displayed and the variable result is set to 100, the value returned by the block. If the expression Currency instanceList count > 100 evaluates to FALSE, the second block is evaluated. The string "Few Currencies" is displayed and the variable result is set to 1, the value returned by the block.
Since the blocks supplied as parameters are Vision programs, they can be used to create nested control structures. For example:
!myList <- 200 sequence ; !result <- myList count > 100 ifTrue: [ myList count > 1000 ifTrue: [ "This is a very big list." ] ifFalse: [ "This is a big list." ] ] ifFalse: [ "This is a small list." ] ; result print ;This program will return one of the 3 strings, depending on the number of elements in the list myList and store the string in the variable result. This program can be streamlined using the elseIf:then: and else: messages:
!myList <- Currency masterList ; !result <- myList count > 1000 ifTrue: [ "This is a very big list." ] . elseIf: [ myList count > 100 ] then: [ "This is a big list." ] . else: [ "This is a small list." ] ; result print ;
Boolean Values and NAs
A common source of Selector Not Found errors are the result of sending the ifTrue:, ifFalse:, or ifTrue:ifFalse messages to non-boolean values. For example:
!object <- NA ; object > 0 ifTrue: [ "Good " ] ifFalse: [ "Bad " ]Since the expression object > 0 returns NA and the ifTrue:ifFalse: message is not defined for this class, the warning message Selector 'ifTrue:ifFalse:' Not Found will be displayed. To avoid this message, an extra conditional test could be performed:
!object <- NA ; object isNumber ifTrue: [ object > 0 ifTrue: [ "Good " ] ifFalse: [ "Bad " ] . print ; ] ;In this case, the ifTrue: block is only evaluated if the variable object is a number. If it is, then the string "Good" is printed, otherwise the string "Bad" is printed. No Selector Not Found messages are generated in this form. Several alternatives exist for writing this program without generating the warning messages. For example:
!object <- NA ; object > 0 ifTrue: [ "Good" ] ifFalse: [ "Bad" ] else: [ ] . print ;In this form, the string "Good" is printed if object > 0 evaluates to TRUE, the string "Bad" is printed if it evaluates to FALSE, and nothing is printed if it evaluates to anything else including NA as it does in this case.