"-*- smalltalk -*-"

" @@PLEAC@@_NAME "
" @@SKIP@@ Smalltalk @@SKIP@@ "

" @@PLEAC@@_1.0 "
"In Smalltalk, everything is an object.  Including strings.  Strings are
instances of the class String."

string := '\n'.  "Two Characters, \ and an n - literal form"
string := String with: $\ with: $n.  "As above, but creating the string
by passing messages"
string := 'Jon ''Maddog'' Orwant'.  "Literal string containing single
string := String with: Character cr.  "String with a newline character"
string := 'Jon "Maddog" Orwant'.  "Literal string containing double

"ANSI standard Smalltalk does not allow arbitrary literal string

"Reading a stream of characters up to (but not including) 'EOF'.  Most
String handling in Smalltalk is done using streams (instances of class
Stream or one of its subclasses."

|sourceStream a|
sourceStream := ReadStream on: 'This is a multiline here document
terminated by EOF on a line by itself
a := sourceStream upToAll: 'EOF'.

" @@PLEAC@@_2.1 "
"Even numbers are objects in Smalltalk.  There is no special syntax for
manipulating numbers other than the literal forms of numbers.

For example, evaluating '1 + 2' results in the object 1 being sent the
message '+' with the single argument 2.  The '+' method returns the
object 3.

An object is either a subclass of Number (in which case it is a number)
or it's not.  An instance of String is not a number, though it might
contain the literal form of a number.

So let's say we have an instance of class String which we think might
contain a number in some form or other..."

result := '123.45' isNumber.   "false is assigned to result. '123.45' is
a String, not a Number."
result := 123.45 isNumber.  "true is assigned to result. 123.45 is
indeed a number."
result := Number readFrom: ('123.45' readStream). "result is the
Fraction(!) 2469/20"
result := result asFloat. "result is now the Float 123.45"
result := Number readFrom: ('this is not a number' readStream). "result
is the Integer zero."
result := Number readFrom: ('123abc' readStream). "result is the Integer
result := 'This is not a number' isNumeric. "result is false"
result := '123' isNumeric. "result is true"
result := '123abc' isNumeric. "result is false"
result := '123' asNumber. "result is the Integer 123"

|number result|
number := '123' asNumber.
result := number isInteger.  "result is true"
result := number isRational. "result is true"
number := 123 / 456. "result is the Fraction 41/152"
result := number isInteger. "result is false"
result := number isRational. "result is true"

"Other tests that all Number objects respond to are:

" @@PLEAC@@_3.0 "
"Dates and time are objects in Smalltalk too ... of course!"

Date today. "Evaluates to an instance of class Date."
Time now. "Evaluates to an instance of class Time."
DateTime now. "Evaluates to an instance of class DateTime."

"Here are some examples of the messages that DateTime responds to
instances of Date and Time respond to similar messages as appropriate."

myDateTime := DateTime now.
myDateTime second. " - the seconds part of the DateTime.  An Integer"
myDateTime minute. " - the minutes part"
myDateTime hour. "- the hours part 24hr clock by default"
myDateTime hour24. "- as above, but explicitly the 24 hours clock"
myDateTime hour12. "- as above but with 12 hours clock"
myDateTime dayOfWeek. " -  the integer day index.  1=Sunday"
myDateTime dayOfWeekName. "- day of the week as a Symbol, e.g. #Tuesday"
myDateTime dayOfMonth. "-  day of the month - an Integer."
myDateTime month. "- month of the year.  Month index - an integer."
myDateTime monthName. "- name of the month as a Symbol, e.g. #June"
myDateTime year. " - the year number as an Integer, e.g. 2005"
myDateTime dayOfYear. "- integer day number of the day within the year."

"... and many more.  See the DateTime, Date and Time classes for the
full story."

" @@PLEAC@@_3.1 "
"We saw Date, Time and DateTime objects being created in the
introduction.  Let's now see how we can show the value of these

Date today printString.   " ->  '3-Jun-2005' "
Time now printString.  " ->  '22:09:35' "
DateTime now printString. " -> ' 2005-06-03T22:10:22+10:00' "

"The message >>printString can be sent to any object.  It is up to the
object to return an interesting instance of class String."

" @@PLEAC@@_3.2 "
"We can create arbitrary dates and time using other class methods on the
Date, Time and DateTime classes."


"The following creates a DateTime of the time I wrote this code as if it
was GMT"
myDateTime := DateTime year: 2005 month: 6 day: 3 hour: 22 minute: 18
second: 26.

"The following creates the DateTime with the correct offset for Sydney,
myDateTime := DateTime year: 2005 month: 6 day: 3 hour: 22 minute: 18
second: 26 offset: (Duration days: 0 hours: 10 minutes: 0 seconds: 0).

"And now we can get the seconds from myDateTime."
myDateTime asSeconds.  "Evaluates to an Integer"
myDateTime asSeconds printString. "Evaluates to an instance of String
representing the above integer."

" @@PLEAC@@_3.3 "
"We can also create a Dates and Times from a number of seconds"

| myDateTime aNumberOfSeconds aDate aTime|
myDateTime := DateTime year: 2005 month: 6 day: 3 hour: 22 minute: 18
second: 26 offset: (Duration days: 0 hours: 10 minutes: 0 seconds: 0).
aNumberOfSeconds := myDateTime asSeconds.
aDate := Date fromSeconds: aNumberOfSeconds.
aTime := Time fromSeconds: aNumberOfSeconds.

" @@PLEAC@@_4.0 "
"Arrays are also objects in Smalltalk.
The class Array is a subclass (though not an immediate subclass) of
Collection.  All collections share enumeration and mutation abilities,
though some kinds of collection impose limits.  For example, Arrays are
of a fixed size, so it is not possible to add more elements to an Array
than it's current size - with other kinds of collection, any number of
elements can be added (until you hit a system limit, like running out of

"Arrays have a literal form, unlike other kinds of collection."
"First we assign a litteral Array containing four Strings to the
variable myArray."
myArray := #('this' 'that' 'the' 'other').
"Now we create a nested Array in a similar way.  We end up with an Array
with three elements, the first two being Strings and the third being a
distinct instance of class Array in turn containing two Strings."
myArray := #('this' 'that' #('the' 'other')).

"We can also create arrays by message passing.  So, to repeat the last
last example:"
|outer nested|
nested := Array with: 'the' with: 'other'.
outer := Array with: 'this' with: 'that' with: nested.

" @@PLEAC@@_4.1 "
|a lines|
a := #('quick' 'brown' 'fox').
"The following send >>subStrings to a String.  The result of this is an
OrderedCollection with 5 elements, each element being a String.  To get
an Array, we send >>asArray to the OrderedCollection."
a := 'Why are you teasing me?' subStrings asArray.

"In the next example I'm forcing the cr character into the string to
make the code work either from a code file, or in an image workspace.
The cr in a literal String *should* be respected, but in GNU Smalltalk
2.1.8 it does not seem to be in an image worksheet."
lines := (
    ('The boy stood on the burning deck.%1' bindWith: Character cr),
     'It was as hot as glass.' subStrings: Character cr) asArray.

"Here we create a large array by reading the contents of a file.  The
contents of the file is an instance of class String in this case.
>>contents is crude, but works fine in this case ... if you have
a file called 'mydatafile' in the current directory that contains
printable characters."
bigArray := ((File name: 'mydatafile') contents) asArray.

"Now we concatenate some Strings and convert them to Arrays"
|name banner|
name := 'Gandalf'.
banner := ('Speak, ', name, ', and enter!') asArray.
banner := ('Speak, %1, and enter!' bindWithArguments: (Array with:
name)) asArray.