# Smalltalk80LanguageImplementation:Chapter 07

Chapter 7 Linear Measures

## Linear Measures

```Object

Magnitude***
Character***
Date***
Time***

Number
Float
Fraction
Integer
LargeNegativeInteger
LargePositiveInteger
SmallInteger

LookupKey
Association

Process

Collection

SequenceableCollection

Semaphore

ArrayedCollection
Array

Bitmap
DisplayBitmap

RunArray
String
Symbol
Text
ByteArray

Interval
OrderedCollection
SortedCollection
Bag
MappedCollection
Set
Dictionary
IdentifyDictionary

Stream
PositionableStream
WriteStream
ExternalStream
FileStream

Random

File
FileDirectory
FilePage

UndefinedObject
Boolean
False
True

ProcessorScheduler
Delay
SharedQueue

Behavior
ClassDescription
Class
MetaClass

Point
Rectangle
BitBit
CharacterScanner

Pen

DisplayObject
DisplayMedium
Form
Cursor
DisplayScreen
InfiniteForm
OpaqueForm
Path
Arc
Circle
Curve
Line
LinearFit
Spline
```

The Smalltalk-80 system provides several classes representing objects that measure something with linear ordering. Real world examples of such measurable quantities are (1) temporal quantities such as dates and time, (2) spatial quantities such as distance, and (3) numerical quantities such as reals and rationals.

## Class Magnitude

IS one number less than another number? Does one date come after another date? Does one time precede another time? Does a character come after another one in the alphabet? Is one distance the same or less than another distance?

The common protocol for answering these queries is provided in the class Magnitude. Magnitude provides the protocol for objects that have the ability to be compared along a linear dimension. Subclasses of class Magnitude include Date, Time, and Number. Classes Character (an element of a string) and LookupKey (a key in a dictionary association) are also implemented as subclasses of class Magnitude. Character is interesting as an example of immutable objects in the system and so is introduced in this chapter; LookupKey is less interesting and is deferred until needed in the chapter on collections. A class Distance is not provided in the actual Smalltalk-80 system.

 comparing < aMagnitude Answer whether the receiver is less than the argument. < = aMagnitude Answer whether the receiver is less than or equal to the argument. > aMagnitude Answer whether the receiver is greater than the argument. > = aMagnitude Answer whether the receiver is greater than or equal to the argument. between: min and: max Answer whether the receiver is greater than or equal to the argument, rain, and less than or equal to the argument, max. Magnitude instance protocol

Although Magnitude inherits from its superclass, Object, the message = for comparing the equality of two quantifiable objects, every kind of Magnitude must redefine this message. The method associated with = in class Magnitude is

```self subclassResponsibility
```

If a subclass of Magnitude does not implement = , then an attempt to send the message to an instance of the subclass results in the special error message that a subclass should have implemented the message,as specified in its superclass.

An instance of a kind of Magnitude can also respond to messages that determine which of two objects that can be linearly measured is the larger or the smaller.

 testing min: aMagnitude Answer the receiver or the argument, whichever has the lesser magnitude. max: aMagnitude Answer the receiver or the argument, whichever has the greater magnitude. Magnitude instance protocol

Note that protocol for the equality comparisons = =, ~ = , and ~~ is inherited from class Object. Using Integers as the example kinds of Magnitudes, we have

 expression result 3 < = 4 true 3 > 4 false 5 between: 2 and: 6 true 5 between: 2 and: 4 false 34 min: 45 34 34 max: 45 45

The programmer does not create instances of Magnitude, but only of its subclasses. This is due to the fact that Magnitude is not able to implement all of the messages it specifies, indeed, that it implements one or more of these messages by the expression self subclassResponsibility.

## Class Date

Now that we have defined the general protocol of Magnitudes, it is possible to add additional protocol that supports arithmetic and inquiries about specific linear measurements. The first refinement we will examine is the subclass Date.

An instance of Date represents a specific day since the start of the Julian calendar. A day exists in a particular month and year. Class Date knows about some obvious information: (1) there are seven days in a week, each day having a symbolic name and an index 1, 2, ..., or 7; (2) there are 12 months in a year, each having a symbolic name and an index, 1, 2, ..., or 12; (3) months have 28, 29, 30, or 31 days; and (4) a particular year might be a leap year.

Protocol provided for the object, Date, supports inquiries about Dates in general as well as about a specific Date. Both Date and Time provide interesting examples of classes in the system for which special knowledge is attributed to and accessible from the class itself, rather than from its instances. This "class protocol" is specified in the metaclass of the class. Let's first look at the class protocol of Date supporting general inquiries.

 general inquiries dayOfWeek: dayName Answer the index in a week, 1, 2 . . . . or 7, of the day named as the argument, dayName. nameOfDay: dayIndex Answer a Symbol that represents the name of the day whose index is the argument, dayIndex, where 1 is Monday, 2, is Tuesday, and so on. indexOfMonth: monthName Answer the index in a year, 1, 2, ..., or 12, of the month named as the argument, monthName. nameOfMonth: monthIndex Answer a Symbol that represents the name of the month whose index is the argument, monthIndex, where 1 is January, 2, is February, and so on. daysInMonth: monthName forYear: yearInteger Answer the number of days in the month whose name is monthName in the year yearInteger (the year must be known in order to account for a leap year). daysInYear: yearInteger Answer the number of days in the year, yearInteger. leapYear: yearInteger Answer 1 if the year yearInteger is a leap year; answer 0 otherwise. dateAndTimeNow Answer an Array whose first element is the current date (an instance of class Date representing today's date) and whose second element is the current time (an instance of class Time representing the time right now). Date class protocol

Thus we can send the following messages.

 expression result Date daysInYear: 1982 365 Date dayOfWeek: #Wednesday 3 Date nameOfMonth: 10 October Date leapYear: 1972 1 (meaning it is a leap year) Date daysInMonth: #February forYear:1972 29 Date daysInMonth: #Feb forYear: 1972 28

Date is familar with the common abbreviations for names of months.

There are four messages that can be used to create an instance of class Date. The one commonly used in the Smalltalk-80 system, notably for marking the creation date of a file, is Date today.

 instance creation today Answer an instance of Date representing the day the message is sent. fromDays: dayCount Answer an instance of Date that is dayCount number of days before or after January 1, 1901 (depending on the sign of the argument). newDay: day month: monthName year: yearInteger Answer an instance of Date that is day number of days into the month named monthName in the year yearInteger. newDay: dayCount year: yearInteger Answer an instance of Date that is dayCount number of days after the beginning of the year yearInteger. Date instance protocol

Four examples of instance creation messages are

 expression result Date today 3 February 1982 date fromDays: 200 20 July 1901 date newDay: 6 month: #Feb year: 82 6 February 1982 Date newDay: 3 year: 82 3 January 1982

Messages that can be sent to an instance of Date are categorized as accessing, inquiries, arithmetic , and printing messages. Accessing and inquiries about a particular day consist of

• the day index, month index, or year
• the number of seconds, days, or months since some other date
• the total days in the date's month or year
• the days left in the date's month or year
• the first day of the date's month
• the name of the date's weekday or month
• the date of a particular weekday previous to the instance

Simple arithmetic is supported in the protocol of class Date.

 arithmetic addDays: dayCount Answer a Date that is dayCount number of days after the receiver. subtractDays: dayCount Answer a Date that is dayCount number of days before the receiver. subtractDate: aDate Answer an Integer that represents the number of days between the receiver and the argument, aDate. Date instance protocol

Such arithmetic is useful, for example, in order to compute due dates for books in a library or fines for late books. Suppose dueDate is an instance of Date denoting the day a book was supposed to be returned to the library. Then

```Date today subtractDate: dueDate
```

computes the number of days for which the borrower should be fined. If a book is being borrowed today and it can be kept out for two weeks, then

```Date today addDays: 14
```

is the due date for the book. If the librarian wants to quit work 16 days before Christmas day, then the date of the last day at work is

```(Date newDay: 25 month: #December year: 1982) subtractDays: 16
```

An algorithm to determine the fine a borrower must pay might first compare today's date with the due date and then, if the due date has past, determine the fine as a 10-cent multiple of the number of days overdue.

```Date today < dueDate
ifTrue: [fine ←  0]
ifFalse: [fine ←  0.10 * (Date today subtractDate: dueDate)]
```

## Class Time

An instance of class Time represents a particular second in a day. Days start at midnight. Time is a subclass of Magnitude. Like class Date, Time can respond to general inquiry messages that are specified in the class protocol.

 general inquiries millisecondClockValue Answer the number of milliseconds since the millisecond clock was last reset or rolled over to 0 millisecondsToRun: timedBlock Answer the number of milliseconds timedBlock takes to return its value. timeWords Answer the seconds (in Greenwich Mean Time) since Jan. 1, 1901. The answer is a four-element ByteArray (ByteArray is described in Chapter 10). totalSeconds Answer the total seconds from Jan. 1, 1901, corrected for time zone and daylight savings time. dateAndTimeNow Answer an Array whose first element is the current date (an instance of class Date that represents today's date) and whose second element is the current time (an instance of class Time that represents the time right now). The result of sending this message to Time is identical to the result of sending it to Date. Time class protocol

The only non-obvious inquiry is millisecondsToRun: timedBlock. An example is

```Time millisecondsToRun: [Date today]
```

where the result is the number of milliseconds it took the system to compute today's date. Because there is some overhead in responding to this message, and because the resolution of the clock affects the result, the careful programmer should determine the machine-dependent uncertainties associated with selecting reasonable arguments to this message.

A new instance of Time can be created by sending Time the message now; the corresponding method reads the current time from a system clock. Alternatively, an instance of Time can be created by sending the message fromSeconds: secondCount, where SecondCount is the number of seconds since midnight.

 instance creation now Answer an instance of Time representing the second the message is sent. fromSeconds: secondCount Answer an instance of Time that is secondCount number of seconds since midnight. Time class protocol

Accessing protocol for instances of class Time provide information as to the number of hours (hours), minutes (minutes) and seconds (seconds) that the instance represents.

Arithmetic is also supported.

 arithmetic addTime: timeAmount Answer an instance of Time that is the argument, timeAmount, after the receiver. subtractTime: timeAmount Answer an instance of Time that is the argument, timeAmount, before the receiver. Time instance protocol

In the messages given above, the arguments (timeAmount) may be either Dates or Times. For this to be possible, the system must be able to convert a Date and a Time to a common unit of measurement ; it converts them to seconds. In the case of Time, the conversion is to the number of seconds since midnight; in the case of Date, the conversion is to the number of seconds between a time on January 1, 1901, and the same time in the receiver's day. To support these methods, instances of each class respond to the conversion message asSeconds .

 Time instance protocol asSeconds Answer the number of seconds since midnight that the receiver represents. Time instance protocol

 converting asSeconds Answer the number of seconds between a time on January 1, 1901, and the same time in the receiver's day. Date instance protocol

Arithmetic for Time can be used in ways analogous to that for Date. Suppose the amount of time a person spends working on a particular project is to be logged so that a customer can be charged an hourly fee. Suppose the person started work at startTime and worked continuously during the day until right now; the phone rings and the customer wants to know today's charges. At that moment, the bill at \$5.00 an hour is

```(Time now subtractTime: startTime) hours * 5
```

ignoring any additional minutes or seconds. If a charge for any fraction of an hour over 30 minutes is to be charged as a full hour then an additional \$5.00 is added if

```(Time now subtractTime: startTime) minutes > 30
```

Who is more productive, the worker who finished the job with time logged at timeA or the worker with time timeB? The answer is the first worker if timeA < timeB. Comparing protocol is inherited from the superclasses Magnitude and Object.

Suppose times are computed across days, for example, in computing the time of a car in a four-day rally. If the first day of the rally started at startTime on day startDate, then the time for a car arriving at the finish line right now is computed as follows.

Let the start time be 6:00 a.m.

```startTime ← Time fromSeconds: (60*60,6).
```

on February 2, 1982

```startDate ←  Date newDay: 2 month: #Feb year: 82.
```

The time that has passed up to the start of the current day is

```todayStart ←  (((Time fromSeconds: 0) addTime: Date today)
subtractTime: startDate)
subtractTime: startTime
```

That is, add all the seconds since Jan. 1, 1901, up to the start of today and then subtract all the seconds since Jan. 1, 1901, up to the start of the start date. This is equivalent to adding the number of seconds in the number of elapsed days, but then the programmer would have to do all the conversions.

```(Date today subtractDate: startDate), 24*60,60)
```

By adding the current time, we have the elapsed rally time for the car.

```todayStart addTime: Time now
```

## Class Character

Class Character is the third subclass of class Magnitude we shall examine. It is a kind of Magnitude because instances of class Character form an ordered sequence about which we can make inquiries such as whether one character precedes ( < ) or succeeds ( > ) another character alphabetically. There are 256 instances of class Character in the system. Each one is associated with a code in an extended ASCII character set.

Characters can be expressed literally by preceding the alphabetic character by a dollar sign (\$); thus, \$A is the Character representing the capital letter "A". Protocol for creating instances of class Character consists of

 instance creation value: anInteger Answer" an instance of Character whose value is the argument, anInteger. The value is associated with an element of the ASCII character set. For example, Character value: 65 is a capital "A". digitValue: anInteger Answer an instance of Character whose digit value is the argument, anInteger. For example, answer \$9 if the argument is 9; answer \$0 for 0; answer \$A for 10, and \$Z for 35. This method is useful in parsing numbers into strings. Typically, only Characters up to \$F are useful (for base 16 numbers). Character class protocol

Class protocol, that is, the set of messages to the object Character, provides a vocabulary for accessing characters that are not easy to distinguish when printed: backspace, cr, esc, newPage (that is, form feed), space, and tab.

Messages to instances of Character support accessing the ASCII value and the digit value of the instance and testing the type of character. The only state of a Character is its value which can never change. Objects that can not change their internal state are called immutable objects. This means that, once created, they are not destroyed and then recreated when they are needed again. Rather, the 256 instances of Character are created at the time the system is initialized and remain in the system. Whenever a new Character whose code is between 0 and 255 is requested, a reference is provided to an already existing Character. In this way the 256 Characters are unique. Besides Characters, the Smalltalk-80 system includes SmallIntegers and Symbols as immutable objects.

Instance protocol also provides conversion of a character into upper or lowercase ( asLowercase and asUppercase) and into a symbol (asSymbol).

A simple alphabetic comparison demonstrates the use of comparing protocol for instances of Character. Suppose we wish to know if one string of characters precedes another string in the telephone book. Strings respond to the message at: to retrieve the element whose index is the argument; elements of Strings are Characters. Thus 'abc' at: 2 is \$b. In the following we assume we are specifying a method in class String whose message selector is min:. The method returns a String, either the receiver of the message rain: or its argument, whichever is collated first alphabetically.

```min: aString
1 to: self size do:
[ :index |
(index > aString size) ifTrue: [↑ aString].
(self at: index) > (aString at: index) ifTrue: [↑ aString].
(self at: index) < (aString at: index) ifTrue: [↑ self]].
↑ self
```

The algorithm consists of two statements. The first is an iteration over each element of the receiver. The iteration stops when either (1) the argument, aString, no longer has a character with which to compare the next character in the receiver (i.e., index > aString size); (2) the next character in self comes after the next character in aString (i.e., (self at: index) > (aString at: index)); or (3) the next character in self comes before the next character in aString. As an example of (1), take the comparison of 'abcd' and 'abc' which terminates when index = 4; the answer is that 'abc' is first alphabetically. For (2), suppose we compare 'abde' with 'abce'. When index = 3, \$d > \$c is true; the answer is 'abce'. For (3), compare 'az' with 'by' which terminates when index -- 1; the answer is 'az'. In the case that the receiver has fewer characters than the argument, even when the receiver is the initial substring of the argument, the first statement will complete and the second statement is evaluated; the result is the receiver. An example is the comparison of 'abc' and 'abcd'.

Note that arithmetic on characters is not supported. For example, the following expression is incorrect.

```a ←  \$A + 1
```

The error occurs because a Character does not understand the message +.