FW: Beginner's workspace (was Simplicity Prize)

Torsten.Bergmann at phaidros.com Torsten.Bergmann at phaidros.com
Wed Apr 19 07:54:59 UTC 2000


This is from the Camp Smalltalk Mailing list but I think it is
interesting for Squeak too.

Bye
Torsten


-----Original Message-----
From: Ivan Tomek [mailto:ivan.tomek at acadiau.ca]
Sent: Mittwoch, 19. April 2000 02:17
To: CampSmalltalk at mojowire.com
Subject: Beginner's workspace (was Simplicity Prize)


Hi,

I like Peter's idea of a Beginner's Workspace and wrote a quick draft 
(see below). Since I am a VisualWorks user, I wrote it for VisualWorks, 
but most of it is generic Smalltalk.

I intend to work on this some more, but I would like to know whether 
you think that this is essentially the correct direction.

Ivan


>  2) Provide a New User Workspace.
> What is needed is a workspace that contains a
>  "21 steps for learning the basics of Smalltalk" tutorial.  With lots
>  of code that they can execute, inspect, and print.  This workspace
>  should demonstrate the use of the basic tools:  inspectors, 
browsers,
>  debuggers, etc.

----------------------------

Introduction to Smalltalk in x easy steps

This Workspace introduces the main concepts of VisualWorks Smalltalk. Its
contents are executable and you should try all our suggested exercises.
There is much more to Smalltalk and the references listed at the end provide
additional information.

Part 1: Objects and messages

1. Everything in Smalltalk is on object, and all work is done by sending
messages to objects.

To execute the following examples,
- select the text using the left mouse button (as in a word processor)
- execute text with Print it command in right mouse button <operate> menu:

3 squared			"receiver is small integer 3"
'abc' asUppercase	"receiver is string 'abc' "
200 factorial

Smalltalk syntax: Object always comes first (receiver), message follows.

2. There are exactly three kinds of messages: Unary, binary, and keyword

Unary (message is a 'word', there are no arguments):
3 negated
'abcdefg' vowels

Binary (message is a special character such as + - , and it is followed by
exactly one argument)
3 + 5		"message (properly message selector) is +, argument is small
integer object 5)
'abc' , 'xyz'	"message selector is , and argument is 'xyz')

Keyword (message is one or more keywords (word followed by :), each keyword
followed by argument)
3 between: 5 and: 10	"message selector is between:and: and arguments are
5 and 10"
$d between: $a and:$r	"receiver is character d, message selector is
between:and: and arguments are characters a and r"
3 raisedTo: 17			"message selector is raisedTo: and argument
is 17"
Dialog request: 'Your name, please' initialAnswer: 'John'

3. Each message returns an object and messages can thus be combined

(5 factorial) between: (3 squared) and: (3 raisedTo: 5)

4. Messages are executed from left to right; bracketed first, unary first,
binary next, keyword last

3 + 2 raisedTo: 2 squared
is the same as
(3+2) raisedTo: (2 squared)

This rule applies to everything, there are no other message preferences. So

5 + 3 * 4
is the same as
(5+3)*4

5. A sequence of messages to the same receiver can be cascaded

In the following examples, select the two consecutive lines of code
(including the comment) and execute with Do it from <operate> menu. Look at
the Visual Launcher to see the result.

Transcript clear.				"Note period separating this
statement from the next"
Transcript show: 'Hello world'
has the same effect as
Transcript clear;				"Note semicolon instead of
period"
	show: 'Hello world'		"Receiver is not repeated"

6. Variables

You can assign an object to variable for later use. Object not assigned to a
variable immediately become unavailble and are automatically removed by the
garbage collector.
All variables must be declared before the first statement. The declaration
lists variable names but does not specify any type.

| price tax total |
price := (Dialog request: 'Please enter price' initialAnswer: '100')
asNumber.
tax := (Dialog request: 'Please enter price %'  initialAnswer: '10')
asNumber.
total := price + (price * tax / 100).
Transcript clear;
	show: 'price: ', price printString; cr;
	show: 'tax: ', tax printString; cr;
	show: 'total: ', total printString

Part 2: Classes and their instances

1. An object may have properties (state)

A person object may have a first name and a last name - two properties.
A book may have an author, a title, a publisher, and contents - four
properties.
To examine the properties of the obeject returned by the following
expression, execute with Inspect from the <operate> menu
3 @ 5
Rectangle origin: (3 @ 5) corner: (25 at 30)
The rectangle above is a composite object - its component have properties.
To see them, execute 'Dive' in the <operate> menu of the inspector. (To
return to previous level, execute 'Pop'.)

2. Every object is an instance of a class

3 is an instance of class SmallInteger - check this by executing each of the
following lines with Print it
3 class
3 @ 5
Rectangle origin: (3 @ 5) corner: (25 at 30)
Question for you: What is the class of $3, the class of '3' ?

3. A class is a template for creating its instances

A class defines the instance variables in which an object stores its
properties, and the messages that the object understands. (definitions of
messages are called methods.)

To see the definition of a class, use the Browser. Open one from the
launcher (command Browse or button) and look at the definition of class
Point. (Execute Find from the <operate> menu of the upper left view).

Questions: What are the instance variables of classes Point and Fraction?

4. Smalltalk library of classes is divided into categories

Categories are shown in the upper left view. Each class is in a category,
categories don't overlap.
The only purpose of categories is to group related classes.

Question: What are the categores of Rectangle, Date, String?

5. A class is an object and understands its own set of messages

Class messages are mostly used to create instances: print individually
Circle center: 23 @ 12 radius: 15
Time now
Date today
This message returns a Date object, an instance of Date, and you can send it
a Date instance messages such as
Date today previous: #Monday
Question: #Monday is not a string, what kind of object is it?
Class names begin with upper case letters so you can see that center:radius:
is a class message.
Sometimes, class messages return relevant related information. Print
Date daysInYear: 2000
This message returns

6. A class may have many methods; methods are thus grouped into protocols

Protocols are only for organizing methods, just like categories organize
classes. Use the Browser to view them.
In the Browser, the views at the top are (left-to-right):
- categories
- classes in selected category
- protocols in selected class
- methods in selected protocol (when you select one, the text view at the
bottom shows its definition)
Buttons instance and class are for selecting whether you want to see
instance methods or class methods.

Questions: 
What are the class protocols of Date? What are its instance protocols?
What are the methods in the Date instance protocol inquiries?

7. Class hierarchy - inheritance

Every class (except one) has exactly one superclass and inherits its class
and instance methods and variables.
To see what it is, select the class in the Browser and look at the
definition in the text view at the bottom.
Question: What is the superclass of SmallInteger, Date, Rectangle?
If A is a superclass of B, B inherits all A definitions. If B is a
superclass of C, C inherits all B definitions, and thus all A definitions as
well. Inheritance is transitive.
Going up the inheritance chain, you eventually reach class Object, the
superclass of all classes. All classes inherit all definitions of Object.
To see the class hierarchy of a class (all its superclasses and subclasses),
select the class in Browser and select Hierarchy in the View menu bar
command (don't select any protocols).
Question: What are all superclasses and subclasses of class Integer?

Part 3: Essential classes and methods

VisualWorks library contains too many classes for any one person to know.
The following are the essential one.
Note that there are not only more useful classes but also many more useful
messages. To find about them, use the Browser.

1. Object
All classes inherit its methods. The most common ones are

- printString - converts an object to a string as in 
3 printString or (13 at 15)printString or 
use it when you need a string :-)
Equality and equivalence (identity)
= means that two objects are equal in some programmer-defined way
== means that they are one and the same object.
So two book objects may be defined as equal when they have the same author
and title. Then two books with the same author and title but different
publisher will be equal but not equivalent.
~= means not equal
~~ means not equivalent

2. Numbers
This is a group of classes including integers, floats, fractions,
fixed-point numbers, complex numbers (extension from included parcel - see
later), and others. Numbers have the obvious protocols for arithmetic and
mathem
atical functions. Check them out, for example, in class ArithmeticValue and
try (Print it)
3 + 6 / 5
15 log
0.3 sin

3. Strings, symbols, characters, dialogs

Strings understand messages for inserting substrings, searching, and other
useful things. Look at the protocols in class String and its superclasses
and try the following with Print it:

'abc' < 'xyz'
'abcdefg' findString: 'de' startingAt: 1	"Important: Indexed
collections of objects such as strings begin at index 1"
'abcdefg' size

A string is a collection of characters and literal characters are obtained
as in
$a
$3
Character is a subclass of Magnitude (as is Date and Time and all number
classes) and can thus be compared as in
$a < $d
Some useful characters can be obtained from the class using class messages
such as
Character cr
Character esc

Symbols are just like strings but they are unique whereas strings are not.
Try

'abc' = 'abc'
'abc' == 'abc'
and (for symbols)
#abc = #abc
#abc == #abc

Symbols are required as arguments in some messages, but their main use is
for method selectors. So their instance protocols include
#+ isKeyword
#between:and: keywords
and others. Try them out.

Class Dialog contains a number of useful messages for obtaining data from
the user. All are class messages. Try

Dialog request: 'What is your name?' initialAnswer: 'Mr. T'	"Returns a
string"

Dialog 		"Returns selection given by the values: argument"
		choose: 'Which one do you want?' 
		fromList: #('first' 'second' 'third' 'fourth') 
		values: #(1 2 3 4) 
		lines: 8 
		cancel: [#noChoice]

Dialog confirm: 'Delete all horrible memories?' 	"Returns true or
false"

Dialog warn: 'This is a warning'	"Returns nil - the UndefinedObject"

4. Boolean

Classes True and False. Used mainly for control of flow. Try
(4 < 5) ifTrue: [Transcript clear; show: '4 is less than 5']
(14 < 5) ifTrue: [Transcript clear; show: '14 is less than 5']
(4 < 5) ifTrue: [Transcript clear; show: '4 is less than 5']
		ifFalse: [Transcript clear; show: '4 is NOT less than 5']
(14 < 5) ifTrue: [Transcript clear; show: '4 is less than 5']
		ifFalse: [Transcript clear; show: '4 is NOT less than 5']

The construct including statements in square brackets is called a block
closure (or simply a block). A block is an object containing several
statements that are evaluated as dictated by the program.
You can also apply logical operations such as
(3 < 4) & (5 < 6)		"logical AND"
(3 < 4) | (5 < 6)		"logical OR"
(3 < 4) not			"logical negation"

And and not also have the following versions:
(3 < 4) and: [5 < 6]
(3 < 4) or: [5 < 6]

The first form evaluate both sides, the form with blocks does not evaluate
the block if it is not necessary.
Question: Write a test to check that the 'partially evaluating' version does
not evaluate the block when not necessary.

5. Blocks

Blocks are instances of class BlockClosure. They are used for many things
but one of the most common uses is iteration - evaluation of a block over
and over while a condition holds, does not hold, etc. Try the following c
ode fragments:
| count |
count := 0.
[count < 100] whileTrue: [count := count + 1].
Transcript clear; show: count printString

| count |
count := 0.
[count squared > 100] whileFalse: [count := count + 1].
Transcript clear; show: count printString

| count |
count := 0.
[count := count + 1. count < 100] whileTrue.
Transcript clear; show: count printString

Transcript clear.
3 timesRepeat: [Transcript show: 'Testing!'; cr]

Transcript clear.
1 to: 5 do: [: n| Transcript show: n printString; tab; show: n squared
printString; cr]

This block has a block argument. That's because the definition of message
to:do: requires it. In this case, the argument simply assumes consecutive
values of 1, 2, and 3.
Question: Is there a method that allows you to specify the step. (Hint:
Think of the class in which it would be defined.)
6. Collections

Collections are one Smalltalk's greatest strengths. They include collections
with indexed elements (array, ordered collection, sorted collection, and
others), and unordered collections (such as sets and dictionaries). Ind
exed collections are indexed from 1.

The main protocols are
creation: typically use new or new: as in (try it)
Array new: 5
OrderedCollection new

converting: convert one kind into another - try and observe the result
#(13 56 23 8) asSortedCollection		"the receiver is a literal
array"
#(1 1 1 3 5 6 6 2 2) asSet

enumeration: accessing collection elements and possibly doing something with
them. Try the following:

Transcript clear.
#(1 2 3 4) do: [:element| Transcript show: element squared printString; cr]
"use Do it"

#(1 5 2 89 34 53) select: [:element| element > 28]
"use Inspect or Print it"
#(1 5 2 89 34 53) reject: [:element| element > 28]
"use Inspect or Print it"
#(1 5 2 89 34 53) collect: [:element| element > 28]
"use Inspect or Print it"

All collections understand all these messages and all Smalltalk programmers
use them extensively.
Check the enumeration protocol of Collection and its subclasses for more.

testing: mainly testing whether a collection contains an element. Try
#(1 2 3 4 5) includes: 4
#(1 2 3 4 5) contains: [:number| number squared > 50]

Briefly about specific collection classes:
Collection is an abstract class - it has no instances and its only purpose
is to define everything that all collections share. Its most important
concrete subclasses are

Array - fixed size, very efficient in operation, automatically checks that
index is within bounds. Cannot grow.
OrderedCollections - similar to Array but can grow - grows automatically
when its curent capacity is filled.
SortedCollection - like OrderedCollection but automatically sorts its
elements. By default uses sort block
[:element1 :element2 | element1 < element2]
to decide whether element1 should be located before element2 or not. But you
can define your own sort block, as in
#(1 2 3 4 5 6 7 8) asSortedCollection: [:x :y| (x rem: 4) < (y rem: 4)]
"What is this? Try it."
Set - unordered collection, no index, automatically eliminates duplicates:
#(1 1 1 2 2 2 3 3 3) asSet
Dictionary - a set of Associations, where an association is a key-value
pair, as an entry in a dictionary. Try
Dictionary withKeysAndValues: #('overdo' 'do to death, go to extremes'
'overheated' 'agitated, excited' 'playmate' 'buddy, companion')

Part 4: Developing a Smalltalk application

 What does it mean to develop a Smalltalk application?

A Smalltalk application is a collection of classes and when the application
runs, it creates objects that send messages to one another. There is no
'main program' or 'main object'.
Typically, an application has a user interface with one or more windows, and
its operation is triggered by user actions.
Most of the classes in the application come from the library (numbers,
windows, etc.), some may be extended by the programmer, and some classes are
typically developed specifically for the application - for example Book, 
Patron, Clerk, and Catalog for a book library application.
Classes are typically divided into two groups - the domain classes that
represent objects from the problem domain (such as Book, Patron, Clerk, and
Catalog above), and user interface classes (windows with widgets).
Typically, an application is started by sending the open message to its main
window. As an example, the Browser is an application and you can open it by
executing (with Do it)
FullSystemBrowser open
or, for a different configuration
FullSystemBrowser openOnAllNamespaces

2. Defining a new method
To define a new method, select either the instance or the class view in the
Browser, select a protocol (to create a new protocol, use Add in the
protocol view), and then write the method according to the template, as in (
presumably to be defined in ArithmeticValue)

cubed
"Calculate the cube of a number"
	^self * self * self

Then click Accept in the <operate> menu and if you have not made any
mistakes, the new mehod will be added to the library. (To save it in the
'image' file, you must save from the launcher, either now or later, using
Save 
as, or you can save on exit.)
A few notes:
- self refers to the receiver, as an example, in 3 cubed, self would be 3
- ^ means 'return the result of the following expression. This cause the
method to terminate execution and exit, returning the specified result. If
you don't exit with the ^ operator, the method will return the receiver. 
To see the difference, look at method clear in class TextVCollector (defines
the Transcript and does not use the ^ operator) and use Print it to evaluate
Transcript clear
It returns the sender - a description of the Transcript.

3. Debugging
Your method may not work the first time. If this happens, Smalltalk will
open an Exception window that can be used to open the debugger to see what
is wrong and made corrections. The Exception window also opens if you sen
d the wrong message to the wrong object. Try

3 asUppercase

and you will get the exception SmallInteger doesNotUnderstand #asUppercase.
If you open the debugger, you will see a stack of messages currently active,
with the failing message near the top. If you select it, you will se
e its definition.
You can also insert a 'breakpoint' to interrupt execution at some point and
continue executing step by step. Try

| price tax total |
price := (Dialog request: 'Please enter price' initialAnswer: '100')
asNumber.
tax := (Dialog request: 'Please enter price %'  initialAnswer: '10')
asNumber.
self halt.
total := price + (price * tax / 100).
Transcript clear;
	show: 'price: ', price printString; cr;
	show: 'tax: ', tax printString; cr;
	show: 'total: ', total printString

Smalltalk will open an Exception window saying 'Halt encountered'. Open the
debugger, select 'unbound method' (that's the code from this workspace, and
continue executing it using either Step or Send - try it. The view at
 the bottom are inspectors on the instance variables of the receiver (left)
and temporary variables and message arguments (right).
You can change the code of the method (execute Accept when done) and
continue. You can also change the values in the two inspectors at the
bottom.

4.Defining a class

Class are collected in namespaces. A namespace is simply a way to get around
the problem that in previous versions of VisualWorks, class names had to be
unique. This meant that two different applications could only be com
bined if their developers didn't use the same name for any of the classes in
their respective products. A namespace makes it possible to ignore class
names in other namespaces - within one namespace, class names must be u
nique, but two different namespaces may contain classes with identical names
without any conflict.
To create a class, you must thus decide on the namespace - either use an
existing one or create a new namespace. See on-line help for details.
The next step is to decide on a category for your class. Select an existing
one if appropriate, or create a new one if necessary, using the <operate>
menu in the category view of the Browser.
The next decision is to select the superclass of your new class. A subclass
is generalization, and a subclasses is specialization. So your superclass
should be a class that performs a more general purpose than your new cl
ass. As an example, Vehicle and Car are a reasonable superclass - subclass
pair. Similarly Account and SavingsAccount.
If you can't think of a suitable existing superclass, make your class a
subclass of Object.
Next, fill in the template for a new class. It appears in the Browser when a
category is selected but no class. It looks like this:
Smalltalk.Root defineClass: #NameOfClass
	superclass: #{NameOfSuperclass}
	indexedType: #none
	private: false
	instanceVariableNames: 'instVarName1 instVarName2'
	classInstanceVariableNames: ''
	imports: ''
	category: 'Interface-Dialogs'
Edit the text by using your clas name on the first line, superclass name on
the second line, and adding instance variables on the fifth line. (The rest
are more advanced parameters that you initially don't need.) Then exe
cute Accept from the <operate) menu.
And then add instance and class protocols as necessary.

5. Developing an application

Developing an application means extending existing classes and adding new
ones. This subject is beyond the scope of this introduction but many
Smalltalk programmers like to use the very direct methodology known as
Extreme Programming or XP and described in Kent Beck's book referenced
below.
In developing the application, you will probably first develop and test
domain objects, and then implement the user interface. Developing the user
interface is relatively easy with the UIPainter tool of VisualWorks that
allows you to 'paint' windows with widgets on the screen and link them with 
your domain objects. The on-line help accessible from the launcher explains
the details.

References

Ivan Tomek,
Jodrey School of Computer Science
Acadia University
Nova Scotia, Canada
fax: (902) 585-1067
voice: (902) 585-1467
e-mail: ivan.tomek at acadiau.ca





More information about the Squeak-dev mailing list