CSE 505 Lecture Notes:

Smalltalk

October 14, 1994


Background

Smalltalk-72 originally developed as a language for the Dynabook (1977 article: describes fonts, painting programs, animation, computer music, simulation, mouse, ...)

developed by Learning Research Group at Xerox Palo Alto Research Center in the 70's and early 80's

some principal players: Alan Kay, Dan Ingalls, Adele Goldberg

metaphor for programming the Dynabook: simulation
(other metaphor that was considered: information retrieval)

Characteristics of Smalltalk-72:

Characteristics of Smalltalk-80: Smalltalk-80 is now a commercial product (ParcPlace Systems, Digitalk, Object Technology International), and a hot item on Wall Street and the MIS world

If you have time, read an account of the the social and political history of Simula and Smalltalk, by clicking here.

Smalltalk influenced the development of other object-oriented languages, such as C++, Objective C, CLOS, Beta, Trellis/Owl, Emerald, Self


Running Smalltalk

To run Smalltalk on a SPARCstation in CSE:

Set up your display variable correctly. For example, if you are on host mollusc, and running Smalltalk on the machine norge, on mollusc type

xhost +norge and on norge type setenv DISPLAY mollusc:0 After getting the display set up correctly, execute this: /var/mnt/visual/bin/st80 /var/mnt/visual/image/visual.im After Smalltalk starts up, inside the "installation workspace" change the code that says SourceFileManager default ... to: SourceFileManager default file: 1 name: '/var/mnt/visual/image/visual.sources' writable: false; file: 2 name: 'st80.changes' writable: true. i.e. change where the source file is found. (This is a file with all the source code in the system; the system browser uses this.) This will also put a file st80.changes in your directory, which keeps track of your modifications and additions to the system.

When you exit, you can save your work by picking "quit" in the Launcher, then "save then quit" in the submenu.

If there are problems running on the Suns, we can also get accounts on the MSCC Macintoshes in the basement of Thompson.


Language Overview

Basic concepts: Syntax: Precedence:


Example 1: Stack

Object subclass: 'Stack' instanceVariables: 'store top' push: item top := top+1. store at: top put: item pop | item | item := store at: top. top := top-1. ^ item setsize: n store := Array new: n. top := 0. Adding error checking and growing: push: item | save | top := top+1. top > store size ifTrue: "store is about to overflow. make a new array twice as big, and copy the old values into it" [save := store. store := Array new: 2*save size. 1 to: save size do: [:k | store at: k put: (save at: k)]]. store at: top put: item pop | item | self isEmpty ifTrue: [self error: 'trying to pop an empty stack']. item := store at: top. top := top-1. ^ item isEmpty ^ top=0

This example is stored on /homes/june/borning/smalltalk/Stacks.st

To file it in to your Smalltalk image, copy it to your directory and evaluate:

(Filename named: 'Stacks.st') fileIn.

Smalltalk Environment


Message lookup

Object \ \ Window \ \ PanedWindow Object printOn: stream ... ---------- Window show self drawBorder. self showTitle. drawBorder .... showTitle .... __________ PanedWindow show super show. self showPanes. showPanes ...


Control structures

All control structures are done with blocks (closures) and message passing

This is characteristic of pure object-oriented languages, but not of hybrid languages

Object | | Boolean / \ / \ True False | | | | true false

True

printOn: stream stream nextPutAll: 'true' & b "evaluating and" ^ b | b "evaluating or" ^ true not ^ false and: block "short-circuit and" ^ block value or: block "short-circuit or" ^ true

False

printOn: stream stream nextPutAll: false' & b "evaluating and" ^ false | b "evaluating or" ^ b not ^ true and: block "short-circuit and" ^ false or: block "short-circuit or" ^ block value

Examples of Boolean expressions:

(3=4) & (2>1) (3=4) | (2>1) (3=2) not true & false not (3=4) and: [(1/0) = 8]

Conditionals

True ifTrue: block ^ block value ifFalse: block ^ nil ifTrue: tBlock ifFalse: fBlock ^ tBlock value False ifTrue: block ^ nil ifFalse: block ^ block value ifTrue: tBlock ifFalse: fBlock ^ fBlock value

Examples of Conditionals:

3=4 ifTrue: [x := 10]. x=y ifTrue: [x := 8] ifFalse [x := 9]. x := x=y ifTrue: [8] ifFalse [9].

Loops

a := 1. [a < 10] whileTrue: [Transcript show: a. a := a+1]. a := 1. [a > 10] whileFalse: [Transcript show: a. a := a+1]. 1 to: 10 do: [:x | Transcript show: x]. How to define whileTrue (not really done this way, though): Block whileTrue: otherBlock self value ifTrue: [otherBlock value. self whileTrue: otherBlock]. whileFalse: otherBlock self value ifFalse: [otherBlock value. self whileTrue: otherBlock].


User-defined control structures

Block repeatUntil: testBlock self value. testBlock whileFalse: [self value]. Most common use: iterating over a collection of some sort Collection | _______________|__________________ / / \ \ Array Set Dictionary SortedCollection | | String Collection copy "evaluate aBlock for each element" do: aBlock "like Lisp mapcar -- make a new collection by applying aBlock to each element and collecting the results" collect: aBlock "return a new collection of the elements that pass the test" select: aBlock "return a new collection of the elements that fail the test" reject: aBlock "like Miranda foldr" inject: startValue into: binaryBlock Most of these can be defined in Collection and inherited: collect: aBlock | newCollection | "make a new collection of the same class as me" newCollection := self class new. self do: [:x | newCollection add: (aBlock value: x)]. ^ newCollection select: aBlock | newCollection | "make a new collection of the same class as me" newCollection := self class new. self do: [:x | (aBlock value: x) ifTrue: [newCollection add: x]]. ^ newCollection inject: startValue into: binaryBlock | result | result := startValue. self do: [:x | result := binaryBlock value: result value: x]. ^ result

Examples:

a := #(3 4 5 6). "an array literal" "this is the same as a := Array new: 5. a at: 1 put: 3. a at: 2 put: 4. etc. " a collect: [:j | j+10] "this returns (13 14 15 16)" a select: [:j | j>4] "this returns (5 6)" a inject: 0 into: [:a :b | a+b] "this returns 18"