Chapter 5

Using Primitives
and Literal Expressions

One of the most commonly used sets of classes in the Telescript language is the set of primitive classes--that is, the class Primitive and its subclasses. Primitive classes define primitive objects such as integers, real numbers, nils, characters, bits, and so on. These objects are often called simply primitives. Primitives are fundamental objects used to express values in many situations--providing operation arguments or setting an object's properties, for example. Knowing how to work with primitives is a crucial skill for any Telescript programmer.

This chapter introduces you to each of the Telescript primitive classes and shows you the features of each class. It also introduces you to the root class of all flavor classes--Object--and shows you a couple of mix-in classes that give primitive classes many of their characteristics. Because primitives are so often used in literal expressions, this chapter takes a closer look at literal expressions and how they're used to create instances of primitive classes.

Primitive Classes

Primitive classes, as stated earlier, are the class Primitive and its subclasses. These classes appear in boldface in the class tree that follows. Two mix-in classes--Ordered and Cased--also appear in boldface. We'll discuss them as well in this chapter.

Object

* Primitive (Protected)
* * Bit (Ordered)
* * Boolean (Ordered)
* * Character (Cased, Ordered)
* * Identifier (Ordered)
* * Nil
* * Number (Ordered)
* * * Integer
* * * Real
* * Octet (Ordered)
Cased

Ordered

The classes Primitive and Number are abstract classes. They can't be instantiated, so you can't create a Primitive object or a Number object. They exist to define features that are inherited by the concrete subclasses below them. You can instantiate these concrete subclasses to create Bit objects, Real objects, Octet objects, and other primitives.

One very important aspect of primitives that separates them from all other types of objects is that each primitive has a primitive value. A primitive value is a datum: an integer number, a real number, a character, a bit, and so on. A primitive value is not a feature, it is an integral part of the primitive. You might say that the primitive value is the primitive. For example, 8 is an Integer object with a value of 8. M is a Character object with a value of M. You can't change the primitive value of a primitive; you can only exchange one primitive for another if you want to change values (in a variable assignment, for example).

The Telescript language defines common data (integers, characters, floating-point numbers, etc.) as primitives so that each datum is an object and can be treated as such in expressions and statements. You'll find that each primitive object has all of the attributes and operations it inherits from its superclasses (including Object), and--in some primitive classes--special features for the class itself. Some of these operations are conversions--an operation that returns an equivalent instance of a different class, typically another primitive. For example, the operation asInteger is a conversion that--when called on a number--returns an integer version of that number, truncating if necessary. Calling asInteger on the real number 65.02 returns the integer 65.

The descriptions that follow introduce you to the features available in each primitive class. If you'd like to read a full description of a primitive's class features, you'll find them under each primitive class entry in Part 4 of the Telescript Language Reference. Remember that each primitive class inherits features from its superclasses, so you should look at descriptions of superclasses such as Object, Primitive, and Ordered to see what features they pass on to primitives.

We'll start our descriptions in this chapter with a look at the class Object, and will then move down the class tree to Primitive, its subclasses, and the mix-ins used to give character to those subclasses. But before we get into the classes themselves, we'll take a quick look at literal expressions--the type of expression in which a primitive object is created.

Literal Expressions

A literal expression is a value, standing by itself, that creates an object. You'll see many examples of literal expressions throughout Telescript code. For example, they're often used in assignments such as:

trips = 3;
The 3 in this case is the literal expression--an integer. The literal expression asks the Telescript engine to create an object of that value. In this assignment example, the engine creates an integer object with the value 3.

When you use a literal expression, you have to indicate precisely the type of object you wish to create so the compiler will read it correctly. As you'll see in upcoming descriptions of primitive classes, different classes have different literal expression syntaxes. For example, to specify the hexadecimal value for an octet object, you precede the value with a dollar sign ($). Bit values are preceded by a percent sign (%), characters are enclosed in single quotes (' and '), and so on. You'll find literal expression syntax discussed in each primitive class description.

You should note that although a literal expression usually specifies a primitive object such as an integer or a character, there are a few that specify non-primitive objects such as strings, bit strings, and octet strings (all discussed in later chapters). For example, a string literal is a sequence of characters enclosed in double quotes (" and ") as this example shows:

"Macromorphological musing"
It specifies a string object containing the characters within quotes.

Let's move on now to descriptions of classes.

The Object Class

The class Object plays a unique role in the pantheon of Telescript classes: it is the root of all flavor classes, the source of all objects, the top of any flavor class tree. It is the one Telescript flavor class that is guaranteed not to have a superclass, and it is superclass to all other flavor classes. Any object that exists on a Telescript engine is a member of class Object and inherits features from Object. The only classes that don't inherit from Object are mix-in classes, which can't be instantiated, and must be mixed into a flavor class that does inherit from Object.

Object itself can't be instantiated; it's an abstract class designed to pass its features on to subclasses which may be instantiated. Some of those inherited features control advanced aspects of Telescript objects. We won't discuss advanced features in this chapter. They'll come in later sections of this book. If you're curious, you can look them up in the Telescript Language Reference. <<<The references to the Telescript Reference Manual will be replaced with the new class reference book when it's completed.>>> We'll look instead at seven of Object's simplest features.

Attributes

Object has seven attributes. Two of these attributes provide elementary information about an object. They are:

As an example of these two attributes in use, consider these two request expressions:

82.class
82.size
The first expression gets the class attribute of the integer 82; it returns the class Integer. The second expression gets the size attribute of the integer 82; it returns the integer 4, which means that the integer 82 takes up 4 octets (bytes) of memory.

Operations

Object has twelve operations of different stripes, controlling elementary to advanced aspects of an object. Five of them are elementary operations:

Some examples of these operations used in request expressions:

82.isInstance(Number)
82.isInstance(Integer)
The first of these expressions checks to see if 82 is an instance of the class Number. It is not (it's an instance of Integer, a subclass of Number), so the operation returns false. The second expression checks to see if 82 is an instance of Integer, which it is, so the operation returns true.

Examples of isMember used in request expressions:

82.isMember(Number)
82.isMember(Character)
The first expression returns true because 82 is a member of the class Number. The second expression returns false because 82 is not a member of the class Character.

And an example of copy used in a request expression:

3.14159.copy()
This expression returns 3.14159, which is a copy of the responder. This operation doesn't seem remarkable in the case of a primitive like a real number, but is much more impressive when called on a complex object that may contain many other objects as properties. In that case the entire object, including all the various objects in its closure, is copied and returned.

copy is an operation that's often used when a requester can't work with the responder object as it likes because the responder may not allow alteration by the requester. By making a copy of the responder, the requester can own and work directly with the copied object. You'll read more about copied objects in later chapters of this book.

The Primitive Class

The class Primitive is an immediate subclass of Object and, like Object, is an abstract class that can't be instantiated. Primitive and all of its subclasses are sealed so you can't define new primitive subclasses. This ensures that the only primitives you'll find on a Telescript engine are those defined as built-in Telescript classes. You can't create custom primitive classes.

Primitive is defined using one mix-in class: Protected. Protected adds one key characteristic to those inherited from Object: once a protected object is instantiated, it can never be altered. The Protected inheritance is one reason why a primitive object can't be changed, only replaced with a new primitive of a different value.

Primitive itself adds only one characteristic to the features inherited from Object and Protected: a member of Primitive can only be constructed in a literal expression; it can't be constructed in a constructor expression as non-primitive objects can be. (You'll learn more about literal expressions later in this chapter and more about constructor expressions in Chapter 8.)

The Ordered Mix-In Class

If you look at the class tree for primitive classes, you'll notice that many of them are defined using the mix-in class Ordered. This mix-in defines and passes on three operations that allow two ordered objects to be compared and their order evaluated. (An ordered object is any instance of a class that inherits from Ordered.) The order of the two objects can be any one of four states, each with its own identifier:

Operations

These operations defined by Ordered compare objects and return a value that's dependent on the order of the two objects. Each operation must be called on an ordered object, and accepts a second ordered object as its only argument:

To see how these operations work, look at them in expressions using integers, which are instances of a class that inherits from Ordered.

41.order(24)
This expression compares the responder, 41, to the argument, 24. It returns the identifier after because the responder is after (greater than) the argument.

8.minimum(9)
This expression returns the responder, 8, because it's before the argument, 9. In other words, it returned the minimum of the two objects.

55.maximum(65)
This expression returns 65, the maximum of the two objects.

The mix-in Ordered is used to define many primitive classes: Bit, Boolean, Character, Identifier, Number, and Octet. Each of these classes has its own definition of order--how one instance of the class can come before or after another instance of the same class. For the most part, you won't be concerned with calling Ordered operations directly; they're taken care of by the logical operators >, <, and = that you'll learn about in the next chapter.

The Nil Class

Nil is the only primitive class that is not ordered. That's because it defines an object that can have only a single value: nil. A Nil object indicates the absence of an object of any other class. You'll see nils constantly in the Telescript world: an operation may return a nil if it didn't have a result; you may supply a nil as an argument for an operation if you don't want to supply any other argument--and the operation permits it. A nil is, in essence, a tool for saying "I don't want to (or I can't) supply a value for an argument, a result, a property, or a variable."

Nil has no operation of its own, but inherits operations from Object.

Constructing a Nil

To construct a nil object, use the keyword nil in a literal expression. For example, the literal expression

nil
constructs a nil object. And

crayons = nil;
assigns a nil object (created by the literal expression nil) to the variable crayons.

The Boolean Class

The class Boolean defines an object that can have either of two values: true or false. If you're used to a language such as C, where any non-zero value is true and zero is false, it's important to note that a boolean object is simply true or false. It has no numerical equivalent.

Constructing a Boolean

To construct a boolean, use the keyword true or false in a literal expression. For example,

checked_out = false;
uses the literal expression true to create a true value and assign it to the variable checked_out.

Operations

The Boolean class offers a set of logical operations that work with boolean objects:

To see how these operations work, consider the following examples:

true.or(false)
returns true, because performing the logical operation "or" on true and false returns true.

true.and(false)
returns false, the result of performing "and" on true and false.

false.not()
returns true, the result of performing "not" on true.

Boolean operations are not commonly called directly because logical Telescript operators (&&, !, and ||, described in Chapter 6) will do much the same work as these operations.

Ordering Booleans

If you use Ordered operations on booleans, a false comes before a true.

The Bit Class

The class Bit defines an object that can have either of two values: 0 (zero) or 1 (one). Bit has no operations of its own, but inherits operations from Ordered and Object.

Constructing a Bit

To construct a bit, use %0 for zero or %1 for one in a literal expression. For example,

%1
is a literal expression for a bit with a value of one.

Ordering Bits

If you use Ordered operations on bits, a zero comes before a one.

The Octet Class

The class Octet defines an object that has a value of 8 bits (which define a byte). It has a range of 256 binary values from 000000002 through 111111112 (or, in hexadecimal, 0016 through FF16). The bits in the octet are referred to as bit 0 (the rightmost bit) through bit 7 (the leftmost bit).

Octets are typically used to hold byte values, and are often collected in a list as an OctetString object (a class that's discussed in Chapter 9).

Constructing an Octet

To construct an octet, use a literal expression that consists of a two-digit hexadecimal value preceded by a dollar sign to signify that it's a hexadecimal value. For example,

$D4
is a literal expression for an octet with a hexadecimal value of D416 (or a binary value of 110101002).

Operations

Octet provides a single operation of its own:

Consider this example:

$D4.asInteger()
This request expression returns the integer 212, the decimal equivalent of D416.

Ordering Octets

If you use Ordered operations on octets, octets with lower hexadecimal values come before octets with higher hexadecimal values.

The Number Class

The class Number is an abstract class that can't be instantiated; it exists to define a set of operations that are passed on to its two concrete subclasses Real and Integer. Nine of these operations perform arithmetic operations--five of them on a single number (unary operations) and four of them on two numbers (binary operations). The remaining six operations are conversion operations that convert a number to an integer, a real number, an octet, a character, a string, or an octet string.

Binary Operations

These operations provide the four basic arithmetic operations (addition, subtraction, multiplication, and division) between two numbers. The first number is the responder, the second number is the sole argument provided.

Four quick examples of binary operations in request expressions:

3.sum(2)
adds 3 and 2 and returns 5.

5.3.difference(2)
subtracts 2 from 5.3 and returns 3.3.

7.multiply(5)
multiplies 7 times 5 and returns 35.

9.divide(2)
divides 9 by 2 and returns 4.5.

Binary operations, as you can see from these examples, may mix integers and real numbers. The result of mixed numbers in a binary operation is always a real number. The result of two real numbers in a binary operation is always a real number. And the result of two integers in a binary operation is an integer--except for division. Dividing one integer by another integer returns a real number.

You won't often directly call a binary operation on a number because Telescript syntax provides the arithmetic operators +, -, *, and / (discussed in the next chapter). These operators let you perform arithmetic operations in standard forms such as 3+2 instead of 3.sum(2).

Unary Operations

These operations perform an arithmetic operation on a single number: the responder. They accept no arguments.

Examples of these operations used in request expressions:

6.02.negate()
returns -6.02.

(-78).magnitude()
returns 78.

6.9.round()
returns 7.

(-8.34).ceiling()
returns -8.

835.89.floor()
returns 835.

Notice that in the examples where we called an operation on a negative number that we enclosed the negative number in parentheses. The Telescript language requires parentheses around a negative number before you can request a feature of that number.

Conversion Operations

These operations convert a number to an object of a specified class. They accept no arguments. These conversions work in slightly different ways depending upon whether the responder is an integer or a real number.

Examples of conversion operations in request expressions:

8.89.asInteger()
returns the integer 8.

(-5).asReal()
returns the real number -5.0.

254.7.asOctet()
returns the octet $FE. (254.7 is truncated to the integer 254 before the conversion.)

65.asCharacter()
returns the character 'A'.

(-48235.89).asString()
returns the string "-48235.89".

5738.asOctetString()
returns the octet string "$166A".

Ordering Numbers

If you use the inherited Ordered operations on numbers, a number of lesser value comes before a number of greater value. For example, -34.67 comes before 8.

The Integer Class

The class Integer defines an object that has an integer value such as 824, 0, or -83. This class inherits all the operations provided by its immediate superclass Number, and specializes the conversion operations so they apply to integers. These specializations are listed in the Telescript Language Reference--they're pretty straightforward. One operation, asInteger, simply returns the responder because the responder is already an integer. The other operations (asReal, asOctet, asCharacter, asString, and asOctetString) all return the converted equivalents of the integer responder.

Constructing an Integer

To construct an integer object, use a literal expression. You can use any combination of numerals without a decimal point. You may use a minus sign (-) before the numeral if it's a negative value. For example, these literal expressions construct integers:

53
-5
0
Keep in mind that if you use a negative integer in a request expression that the Telescript language requires you to enclose the integer in parentheses as in these examples:

(-5).negate()
(-824).asString()

Operations

Integer supplements its inherited features with two operations. Each accepts an integer as its sole argument:

Using these two operations with the same argument and the same responder allows you to perform integer division that results in both a quotient and a remainder.

The Real Class

The class Real defines an object that has a real number value such as 0.56, -6.11, 0, 8, or 6.0x1023. This class inherits all the operations provided by its immediate superclass Number, and specializes the conversion operations so they apply to real numbers. The operation asReal simply returns the responder because the responder is already a real number. asInteger truncates all numerals to the right of the decimal point to convert a real number to a decimal. The operations asCharacter, asOctet, and asOctetString all convert the real-number responder into an integer through truncation and then convert that integer value to a character, octet, or octet string.

Real adds no features of its own to the features it inherits.

Constructing a Real Number

To construct a real-number object, use a literal expression. A real number has two parts: the mantissa and the exponent. The mantissa may be any number with zero, one, or more digits to the left of a decimal point followed by any non-zero number of digits to the right of the decimal point. 9.165, .844, or 375.2 are examples of well-formed mantissas. 32. is not allowed because it has no digits to the right of the decimal point. A mantissa may also be any number without a decimal point--5, or 783, or 1955 for example.

The exponent is a power of 10 used to multiply the mantissa for the resulting real number--the 6 of 106 is, for example, an exponent.

The mantissa and exponent are combined with the mantissa first, followed by an e (upper- or lowercase), then the exponent. The real number 9.165e6 is, for example, 9.165 times 106, which is 9,165,000.

To construct a real number, you must either use a number with an exponent or--if you don't use an exponent--use a number with a decimal point. If you don't use an exponent for a real number, the exponent is figured as 0 (100, which is 1, leaves the mantissa as it is). For example, these literal expressions are all real numbers:

98.0
-8.25
45e6
6.02E23
A negative real number, like a negative integer, must be enclosed in parentheses if you use it in a request expression. These examples show proper Telescript syntax for features called on negative real numbers:

(-46.89e7).asInteger()
(-1.0955).floor()

The Character Class

The class Character defines an object that has the value of a Unicode character--"P", for example, or "3" or "%" or any number of characters used throughout the world. There are 65,535 possible instances of Character, one for each character (and two noncharacters) of the Unicode standard.

If you're unfamiliar with Unicode, it's a character encoding standard that uses 16 bits to encode each character. This allows the characters of most of the world's languages to be encoded for use in a computer. Unicode's first 128 characters are the same as the 128 ASCII characters, so converting ASCII characters to Unicode is a simple matter of turning 7-bit ASCII values into 16-bit Unicode values by adding nine 0 bits to the left of the ASCII bits.

Unicode values are typically expressed as hexadecimal values, and are shown in text (such as this book) as a 4-digit hexadecimal value preceded by "U+". For example, the character "A", which is typically shown in ASCII as the decimal value 65, is shown in Unicode as the hexadecimal value U+0041. For more information, read The Unicode Standard: Worldwide Character Encoding published by Addison-Wesley. It defines the Unicode standard and shows how the world's characters are encoded using that standard.

Character defines a number of features of its own. It also inherits features from the flavor classes Object and Primitive and the mix-in classes Cased and Ordered. Ordered, as you'll recall, allows you to compare the order of two characters. Cased, as you'll read later in this chapter, defines features that let you know whether a character is upper- or lowercase and allow you to change one case to the other.

Characters are often collected in a list as a String object, a class that's discussed in Chapter 10.

Constructing a Character

To construct a character in a literal expression, use a character enclosed in single quotes. For example:

letterGrade = 'B';
Some Unicode characters are characters like line feed or carriage return that can't be directly represented in a keyboard-entered Telescript program. To construct one of these characters, use the escape sequences defined by ANSI C. Each of these escape sequences starts with a backslash (\) and follows with one or more characters that specify the control character. The entire escape sequence is enclosed in single quotes as in these examples:

'\n'
'\r'
The first of these expressions is a line feed; the second is a carriage return.

These are the ANSI C escape sequences:
Escape SequenceDescription
\nNewline (NL). Also known as line feed (LF).
\tHorizontal tab (HT).
\vVertical tab (VT).
\bBackspace (BS).
\rCarriage return (CR).
\fFormfeed (FF).
\aAudible alert (BEL)
\\Backslash (\).
\?Question mark (?).
\'Single quote (').
\"Double quote (").
\oooOctal number. The ooo following the backslash may be one, two, or three octal digits to express a value from octal 000 to octal 777.
\xhhHexadecimal number. The hh following the x may be one or more hexadecimal digits to express a value from hexadecimal 00 to hexadecimal FF.
\cAny character other than "x", "X", the numerals "0" through "7", or any of the characters that appear in any of the other escape sequences. The c following the backslash is the character to be represented.

Note that you can use either capital or lowercase characters in an escape sequence. For example, both \n and \N denote a line feed character.

Note also that you can't use a backslash, question mark, single quote, or double quote to represent itself as a character in source code--you must use an escape sequence instead. In other words, you must use '\\', '\?', '\'', and '\"' to represent backslash, question mark, single quote, and double quote characters respectively.

Attributes

Character has a set of read-only attributes that you can get to tell if the character is an ASCII character, a decimal digit, a punctuation mark, a space, or an alphabetic character:

Operations

Character also has a single operation--a conversion operation:

Ordering Characters

If you use the inherited Ordered operations on characters, characters with lower Unicode values come before characters with higher Unicode values. For example, 'A' (U+0041) comes before 'a' (U+0061).

The Cased Mix-In Class

The mix-in class Cased is one of Character's immediate superclasses. It defines two attributes and two operations that work with upper- and lowercase text. These features are specialized for Character to work on a single character as described here.

Attributes

Cased's two read-only attributes return case information about a character:

Operations

Cased's two operations change the case of characters:

The Identifier Class

The class Identifier defines a primitive that distinguishes one object from other objects. Identifiers are used to name variables, operations, and other aspects of the Telescript environment. Although an identifier looks--in code--like a string of text, it isn't a string object. Strings are enclosed in double quotes, identifiers are not. The text of an identifier makes it unique: by definition no two identifiers can have the same text. This means that two identifiers with the same text are the same identifier.

Constructing an Identifier

To construct an identifier, use a literal expression that contains text following these rules: The first character of the text must be an alphabetic character. All remaining characters can be anything but a control, private use, punctuation, space, or special character as defined by the Unicode standard.

These rules allow you to create an identifier of any length text. You may use any of many thousands of different characters in an identifier's text. Be sure to consult the Unicode standard for definitions of the character types listed in the identifier text rules.

If you work strictly with ASCII characters and aren't concerned with the extended Unicode character set, the rules for identifier text boil down to this: The first character of the text must be an upper- or lowercase letter (A-Z, a-z). The following characters can be upper- or lowercase letters, numerals (0-9), or an underline.

When you create identifier text, keep in mind that you can't use any of the Telescript reserved words as an identifier unless you prefix it with the escape character "underline" (_). If you use a reserved word as an identifier without preceding it with an escape, the compiler will read the text and act on it as if it were a reserved word. You'll get unexpected (and probably unwanted) results. Note that you can't use an underline at the beginning of identifier text unless the text is a reserved word. These are the Telescript reserved words:
abstractimportsplacesponsor
afterinprivatesponsored
breakinstanceprocessthrow
catchinterfacepropertythrows
classisprotectedto
clientlooppublictrue
continuemagiccapreadonlytry
copiedmixinrefunprotected
domodulerepeatuse
elsenilrestrictwhen
falseopreturnwhile
forownsealedwith
hereownedself 
ifownershared 

The following are some legal identifiers:

dogbait
Cobalt_new_96
figureMe
_loop
add62ToIt
Notice that the fourth identifier, _loop, uses an escape character followed by the reserved word loop. This constructs the identifier loop.

The following are some illegal identifiers:

95windows /* starts with a numeral */
_dropvalue /* starts with an underline and is not followed by a keyword */
else /* is a Telescript reserved word */
too much /* uses a space */
Value#83 /* uses #, an illegal character */

Operations

Identifier has a single operation of its own, a conversion:

Ordering Identifiers

If you use Ordered operations on identifiers, identifier order is determined the same way as the text's string order is determined, a process fully described in Chapter 10. For identifiers with standard Latin-character text, an identifier that is in earlier alphabetical order than a second identifier comes before that second identifier.

* * *

Now that you have a firm grasp on primitives, bring that grasp to the next chapter, where you can drop primitives into a fine stew of operators, variables, and assignments.

5 - Using Primitives and Literal Expressions
Primitive Classes
Literal Expressions
The Object Class
Attributes
Operations
The Primitive Class
The Ordered Mix-In Class
Operations
The Nil Class
Constructing a Nil
The Boolean Class
Constructing a Boolean
Operations
Ordering Booleans
The Bit Class
Constructing a Bit
Ordering Bits
The Octet Class
Constructing an Octet
Operations
Ordering Octets
The Number Class
Binary Operations
Unary Operations
Conversion Operations
Ordering Numbers
The Integer Class
Constructing an Integer
Operations
The Real Class
Constructing a Real Number
The Character Class
Constructing a Character
Attributes
Operations
Ordering Characters
The Cased Mix-In Class
Attributes
Operations
The Identifier Class
Constructing an Identifier
Operations
Ordering Identifiers

TS Ref - 26 JUN 1996

Generated with Harlequin WebMaker