Accessors Add Method Benchmarks Binary Messages Blocks Browse/Do/Inspect/Print It Browse or Edit Method Characters Classes Code Formatting Comments Configuration Constants Create Class Create Category Create New Object Debugger Delete Class Delete Method Enumerated Types Exception Handling FFI Filein/Fileout Find Class File List Flaps Fonts Images Implementers Implementations Indentation Inheritance Inspector Interfaces Introduction Keyboard Input Keyboard Shortcuts Literal/Dynamic Arrays LogicalExpressions MessagePrecedence Messages Method Arguments Method Finder Methods Morphic Monticello Mouse Buttons Naming Conventions OmniBrowser Other Types Packages Persistence Projects Reasons Disliked Reasons Liked Refactoring Reflection Regular Expressions ReservedKeywords Resources Running Headless Seaside Senders Squeak Environment Starting and Quitting Startup and Shutdown Statements Stream I/O Strings SVI Symbols System Browser Transcript Unit Tests Variable References Variables Web Applications Windows Workspace World Menu
The following was adapted from http://www.squeak.org/Smalltalk/.
This is a partial list of open source implementations.
The Smalltalk environment is stored in an "image" file. It contains:
Changes can be saved in the current image or in a new image file.
Classes are templates for creating objects.
They define class variables, instance variables,
class methods, instance methods, and more.
They are organized into categories (similar to packages in Java)
to make them easier to find,
but their names must be unique across all categories.
They are described by Class
objects
that are in the Kernel-Class category.
In Squeak Smalltalk the Class
class
is a subclass of Behavior
.
The concepts of abstract classes and methods are not directly supported
in Smalltalk. A method is essentially abstract if
it returns "self subclassResponsibility
".
A class is essentially abstract if it contains any abstract methods.
To get an Array
containing all the current instances
of a given class, send allInstances
to the class.
For example,
instances := SystemWindow allInstances
.
Smalltalk supports single inheritace, not multiple.
The superclass of every class is specified in its definition
and is often simply Object
.
For example, Object subclass: #FooBar
.
In Squeak Smalltalk, the Object
class
is a subclass of ProtoObject
.
Smalltalk doesn't support the concept of interfaces.
Instead it relies on an extreme form of polymorphism.
Any message can be sent to any object as the object responds to it.
This makes creating mock objects really easy.
If the object doesn't respond to the message then
the method doesNotUnderstand:
will be invoked
with the message name symbol as an argument.
This is defined in the class Object
which
signals a MessageNotUnderstood
error.
The doesNotUnderstand
method can be overridden
to do interesting metaprogramming things.
doesNotUnderstand: aMessage "handle unrecognized messages" Transcript show: 'I don''t recognize "', aMessage asString, '".'
Values representing a single character are specified with
a $ followed by the character. For example, the plus character
is represented by $+
.
The Character
class has class methods that return
whitespace characters such as space
and tab
.
Literal strings are surrounded by single quotes.
This is convenient because it seems that double quotes
are needed inside string values more often than single quotes.
To embed a single quote, use two consecutive single quotes.
To concatenate strings, list any number of literal strings
and/or string variables with commas in between.
For example, m := 'Mark'. f := m, 'Tami'.
f
is now 'MarkTami'
.
To concatenate non-string values to strings, call asString
on them. For example, "n := 3. s := n printString, 'D'.
".
An alternative to converting non-String
objects
to Strings
for the purpose of concatenation
is to use the String
format:
method
whose parameter is a Collection
.
The previous example could be written as follows.
n := 3. s := '3{1}' format: { n }
The receiver String
can contain any number of
indexed placeholders represented by an integer inside curly braces.
The parameter is often created using a dynamic array.
To append one String to another, a new String must be created.
For example, "s1 := s1, s2
".
If many appends must be performed, consider using
a WriteStream
as follows, which is much faster:
s := String streamContents: [:stream | stream nextPutAll: 'foo'; nextPutAll: 'bar' ]
To determine if a string contains a substring,
use the includesSubstring:
method.
To replace every occurrence of a substring with another string,
use the copyReplaceAll:with:
method.
To get a substring from a string, use the copyFrom:to:
method as follows:
s1 := 'abcde'. s2 := s1 copyFrom: 2 to: 4. "sets s2 to 'bcd'" s3 := s1 copyFrom: 3 to: s1 size. "sets s3 to 'cde'"
To get a substring that includes all characters but beginning ones
use the allButFirst
and allButFirst:
methods.
To get a substring that includes all characters but ending ones
use the allButLast
and allButLast:
method.
Symbols are names that are preceded by a #
.
They are used in place of strings when
there should only one instance with the name.
If a symbol name contains special characters such as
spaces, periods or underscores, surround the name with single quotes.
Amazingly the standard Squeak distribution doesn't include
support for regular expressions. However, Squeak-Dev distributions
include the VB-Regex package. VB stands for Vassili Bykov, the author.
Among other things, this package adds methods to the String
class such as matchesRegex:
.
See http://www.dartois-d.nom.fr/regex/en/ for documentation.
'a1b' matchesRegex: '\w\d\w' "answers true"
Types that are primitives in other programming languages
are described by classes in Smalltalk.
For example, the "Kernel-Numbers" category contains the classes
Float
(double-precision), Fraction
and Integer
which are subclasses of Number
.
The "Kernel-Objects" category contains the classes
Boolean
, False
, True
and
Object
.
Constants are typically held in class variables. They are initialized in a class initialize method. This is automatically called when classes are loaded using Monticello. What calls it if this isn't done?
Smalltalk doesn't support the concept of enumerated types like in Java 5 and above. Instead, the Smalltalk way is to:
initialize
method that
creates an instance of the class for each enumerated value
using basicNew
and assigns it the corresponding class variable
new
with
"self error: 'new instances cannot be created'
"
Here's an example ColorEnum
class.
Object subclass: #ColorEnum instanceVariableNames: '' classVariableNames: 'Blue Green Red' poolDictionaries: '' category: 'SomeCategory' initialize Red := self basicNew. Green := self basicNew. Blue := self basicNew new self error: 'new instances cannot be created' red ^Red green ^Green blue ^Blue
Comments are surrounded by double quotes and can span multiple lines.
To add "todo" comments that can be easily found later, enter "self flag: #todo." followed by a regular comment which can be on the same line. To find all occurrences of that, select "todo" and press alt-n which displays all the senders of #todo in a new window. In OmniBrowser, methods containing those have a wrench icon in front of them in the method plane.
These are Squeak extensions, not standard Smalltalk syntax.
Literal arrays create an array from a list of literal values.
The code numbers := #(1 3 7)
creates an array of Integer objects.
The code colors := #(red green blue)
creates an array of symbols.
The code colors := #('red' 'green' 'blue')
creates an array of String objects.
Dynamic arrays (a.k.a. bracket arrays) create an array from
expressions separated by periods.
The code colors :=
{'red' asUppercase. 'green' asUppercase. 'blue' asUppercase}
creates an array of String objects that are the results of
the asUppercase
method.
There are only six reserved keywords.
self
refers to the current object.super
is used to force method lookup to
begin in the superclass.
nil
represents no value and is a singleton instance
of the class UndefinedObject
.
true
and false
are boolean values
that are singleton instances of the classes
True
and False
.
thisContext
represents the top frame of the call stack
which represents the method or block that is currently executing.
The Boolean
class defines many methods for forming
logical expressions.
and:
and or:
short-circuit.
&
and |
do not.
Other methods include not
and xor:
.
Names of local/temporary variables and instance variables start with a lowercase letter and are camelcased. Names of classes, class variables and global variables start with an uppercase letter and are camelcased.
The convention in Squeak Smalltalk is to use a single tab.
There are three kinds of statements in Smalltalk.
self
or super
for the receiver.
There are three kinds of messages: unary, binary and keyword.
For more on these,
see the Messages section below.
Messages can be "cascaded" to send multiple messages to the same object.
This is done by separating the messages with semicolons.
variable := expression
where expression
is
a literal value, variable or message send.
^expression
.
There is also a syntax for defining methods, but this is hidden by the development environment and isn't usually viewed directly.
There are no statements for branching or looping.
Instead, those things are performed by methods in classes like
Boolean
, Interval
and Collection
.
Here's an example if-then-else.
"ifTrue:ifFalse:
" is a method of Boolean
which is what "m > n
" returns.
The show
method of Transcript
writes to the Transcript window if one is open.
m := 4. n := 5. m > n ifTrue: [ Transcript show: 'm is bigger'; cr ] ifFalse: [ Transcript show: 'n is bigger'; cr ]
The equivalent of a switch/case statement is the
Object
method caseOf:otherwise:
.
Here's an example loop through a range of numbers.
"to:
" is an Integer
method
that creates an Interval
object.
"do:
" is an Interval
method
that executes a block for each value in it.
3 to: 7 do: [ :i | Transcript show: i * 2; cr ]
Here's an example loop through an Array
of symbols.
array := #(red green blue). array do: [:item | Transcript show: item; cr]
There are three kinds of messages that can be sent to classes and objects.
5 factorial
).
2 + 3
).
Such methods should end with ^self
to support
chaining of calls.
These are mainly used for mathematical operators.
For other methods that take one argument, keyword messages are used.
For a complete list of binary messages, see
Binary Messages.
19 printPaddedWith: $+ to: 5.
which returns '+++19').
Argument names typically describe the kind of value they expect
(for example, aBoolean
).
Despite being named, the arguments must be specified in the order
in which they are listed in the method definition.
When describing keyword messages, the arguments names are run together.
For example, the Dictionary
class contains a method
described by at:put:
.
Any number of messages can be sent to the same object by chaining them using semicolons. For example,
s := Set new. s add: 1; add: 2; add: 3.
Characters that look like operators from other programming languages are binary messages in Smalltalk. Many are defined in provided classes and they can also be defined in custom classes. There are a fixed set of them and they are all listed below.
+
-
*
/
perform arithmetic<
<=
>
>=
perform relational comparisons=
tests for equality (same values)~=
tests for inequality (different values)==
tests for identity (same objects)==
tests for non-identity (different objects)**
performs exponentiation//
performs integer division\\
performs modulo&
performs logical and (doesn't short-circuit)|
performs logical or (doesn't short-circuit),
concatenate two collections (strings are collections)@
creates a Point
object->
creates an Association
objectSmalltalk doesn't use operator precedence when evaluating statements. Instead it evaluates statements in the following order unless parentheses are used to override the order.
This means that a := 2 + 3 * 4
will result in
a
being set to 20,
not 14 as is the case in most other programming languages.
To get 14, use a := 2 + (3 * 4)
.
This also methods that parentheses are needed in
"v = 1 | v = 2
" because all the messages are binary
and will be evaluated left to right. The correct code is
"(v = 1) | (v = 2)
".
A block is a sequence of statements whose execution is deferred.
They can be thought of as methods with no name (anonymous)
Blocks can take parameters and return a value.
They are represented by instances of the BlockClosure
class
which is in the Kernel-Contexts category.
The syntax for a block is
[ argument-list | statement-list ]
.
This makes sense since real blocks have square corners.
Names in the argument list are preceded by colons
and they are separated by spaces.
For example, "[ :p1 :p2 | code ]
".
If there are no arguments then the vertical bar can be omitted.
Before the statements, a list of temporary variables can be declared
in the same way they are declared
at the beginning of a method.
Statements in the statement list are separated by periods.
The Seaside coding conventions call for a single space
inside the square brackets.
Blocks can be passed as arguments to methods.
Once inside the a method, block arguments can be executed by sending
them many different methods from the BlockClosure
class.
Examples include value
(no args),
value:
(1 arg),
valueWithArguments:
(any number of args in an array),
repeat
,
doWhileFalse:
and doWhileTrue:
.
Blocks are closures which means they remember the variables that were in scope when they were created.
To run the code in a block in another process (or green thread),
see the methods starting with "fork
"
in the BlockClosure
class.
To "sleep" within a process, see the Delay
class.
There are five kinds of variables in Smalltalk.
| var1 var2 var3 |
.
self
.
They are listed in a space-separated string that is the value of the
class definition instanceVariableNames:
argument.
classVariableNames:
argument.
Smalltalk
object
which is a global SystemDictionary
object.
Most of the entries in the dictionary refer to
Class
objects.
poolDictionaries:
argument.
A method is an implementation of a message. Methods are described by the message that invokes them (called the method signature in other languages), a comment, a list of local/temporary variables inside vertical bars and a sequence of statements separated by periods. The method signature can be just a method name (unary), a method name followed by a single argument name (binary), or list of keyword and argument name pairs where each keyword is terminated with a colon (keyword). The list of temporary variables is a space-separated list of variable names surrounded by vertical bars. The reason its good to have to declare variables in this way is to make code typo-proof. If variables just sprang into existence the first time they were used, typos in variables names would create new variables rather than being flagged as errors. The Seaside coding conventions call for a single space inside the vertical bars.
It is a standard in Smalltalk to indent code using tabs instead of spaces.
It's not necessary to manually enter the local/temporary variables between the vertical bars that declare them. When saving the method, the compiler spots undeclared variables and offers the choice of automatically declaring them as either instance or temporary variables. It does this by displaying a dialog with "Unknown variable: {name}" in the title bar and the choices "declare temp", "declare instance" and "cancel".
A method can return a value using ^expression
.
If a value is returned then by convention its comment
should begin with "answers ...".
Methods that don't explicitly return a value will return self.
When methods are cascaded, the value returned by the last method
is the value of the expression.
To make the return value of a cascaded sequence of messages
be the original receiver instead, send "yourself
"
as the last message.
This is often useful in conjunction with creating a new object
that is returned from a method. For example,
^Car new make: 'BMW'; model: 'Z3'; paint: Color yellow; yourself
All methods are accessible to all other methods. The fact that some methods are intended for use only by other methods in the same class is documented by placing them in a protocol named "private".
Accessor methods for getting and setting the values of instance variables
do not, by convention, begin with "get" and "set".
For an instance variable "foo
",
the getter method should be named "foo
" and
the setter method should be named "foo:
".
Accessor methods for all the instance variables can be generated by yellow-clicking in the edit pane and selecting refactor class...accessors. Modify generated setters to have an argument name that indicates the type of object expected.
Exceptions are objects from classes that inherit from the
Exception
class.
Browse the Exception
class and
press the "hierarchy" button to see the predefined subclasses.
There are two direct subclasses,
Abort
and Error
.
All the other predefined exceptions inherit from Error
.
To "signal" (throw in Java) an exception, create the exception object
and send the signal
message to it.
To catch an exception, invoke code that might raise it in a block
and send a message for a BlockClosure
method
such as on:do:
to it.
Here's an example.
thrower "demonstrates throwing an exception" | e | e := Exception new. e messageText: 'something bad happened'. e signal. catcher "demonstrates catching an exception" [ self thrower ] on: Exception do: [ :e | Transcript show: e messageText ]
The BlockClosure
class has an ensure:
method
that executes a given block regardless of
whether an exception is signaled (similar to a Java finally block).
It also has an ifCurtailed:
method
that only executes the block if an exception is signaled.
Also look at these methods in the Exception
class:
pass
,
resignalAs:
,
resume
,
retry
,
retryUsing
,
return
,
return:
I/O is performed using subclasses of the Stream
class.
To read or write a text file, use a FileStream
which is a subclass of ReadWriteStream
.
The following code writes to a new text file.
The nextPutAll
method writes all elements of a collection
to the stream. Note that the String
class
inherits from AbstractCollection
.
Each character in the string is an element of the collection.
fs := FileStream newFileNamed: 'foo.txt'. fs nextPutAll: 'line 1'; cr. fs nextPutAll: 'line 2'. fs.close
The following code reads the text file.
fs := FileStream fileNamed: 'foo.txt'. [fs atEnd] whileFalse: [ | line | line := fs upTo: Character cr. Transcript show: line. ]. fs.close
To obtain the content of a stream as a String, send the
contents
message to it.
The close
method doesn't do anything.
Data can continue to be written to the stream after it is called.
To work with stdin and stdout of the current process, load and use the OSProcess package. The README file says that Mac OS X isn't supported yet. To load the OSProcess package, red-click the desktop and select the following: open..., Universe Browser (basic), System, OSProcess, "select package" button and "Install Selections" button. Here's an example of using it:
process := ThisOSProcess thisOSProcess. stdin := process stdIn. "acts like a Stream" stdout := process stdOut. stderr := process stdErr. stderr print: Time now; cr. "put the time of day on my stderr output"
To find out how long it takes to run a section of code, do the following:
ms := [ code goes here ] timeToRun
To determine whether a variable refers to an object of a given type
use isMemberOf
(instance of given class)
or isKindOf
(instance of given class or a subclass).
For example:
v := 5. (v isKindOf: Integer) ifTrue: [ Transcript show: 'an Integer!' ]
The most popular framework for developing web applications using Smalltalk is Seaside.
Squeak is a descendent of Smalltalk-80. It was created by Alan Kay and Dan Ingalls while they worked at Apple, and continued at Disney. It is moving toward, but not yet compliant, with ANSI Smalltalk. Squeak can be downloaded from http://www.squeak.org/Download/. For versions targeted at developers, look for "Squeak-Dev" on that page.
There are four files associated with Squeak.
The Squeak virtual machine is implmented entirely in Smalltalk code and tested that way. When a new release is made, that Smalltalk code is run through a tool that translates it to C code which is compiled and linked to create a new VM executable.
Prebuilt versions of Squeak can be downloaded for many platforms. To get Squeak for Ubuntu, select Applications...Add/Remove..., select the "All" category, and search for "Squeak".
The main menu in Squeak is displayed by yellow-clicking on the desktop. This is called the "World menu". A large amount of functionality can be accessed from this menu.
To start Squeak, double-click on a .image file. To quit Squeak, select World...save and quit or World...quit.
To collapse or uncollapse a window click the circle icon on the far right end of the title bar.
Here are some common configuration changes for new images.
maxArgumentsPerLine
method
in the RBFormatter
class
to answer something higher than one.In Smalltalk development environments the mouse buttons are referred to as red, yellow and blue. These are mapped differently under different OSes. The mappings are summarized in the table below.
Button | Windows | Mac OS X | Linux/UNIX |
---|---|---|---|
red | left | left | left |
yellow | right | option-click or wheel-click | middle |
blue | alt-left | right or cmd-click or ctrl-click | right |
The yellow and blue buttons can be swapped by opening the World menu, selecting "Preference Browser", selecting "developer image", and enabling "swapMouseButtons".
"Flaps" are tabs that appear around the edges of the main window. Red-clicking them opens a drawer full of tools/applications. Red-clicking them again, or red-clicking another flap on the same edge, closes the drawer. To enable repositioning of the flaps, turn off "automatic flap layout".
To move all the flags to the bottom edge of the main window, open the World menu, select "flaps..." and select "put shared flaps on bottom".
Many keyboard shortcuts start with the ctrl or alt key. On a Mac the command (Apple) key can be used instead of either of these in most cases.
To find given text in the current method,
press ctrl-f and enter the text in a dialog.
To find the next occurrence, press ctrl-g.
To set the search string to the text that is selected, press ctrl-h.
The text that is found can be replaced by
typing over it while it is highlighted.
To make the same replacement in the next occurrence, press ctrl-j.
To make the same replacement in all occurrences, press ctrl-J.
To find all occurrences of given text in all methods, enter the text in a window such as a Workspace, select it, yellow-click, and select more...method source with it. Other items on the more menu include "selectors containing it", "method strings with it", "class names containing it" and "class comments with it".
This tool is useful for trying snippets of code. To get one, drag one out of the "Tools" flap or select World...open...workspace. Enter expresssions, select them and use commands such as browse it (ctrl-b), do it (ctrl-d), explore it (ctrl-I), inspect it (ctrl-i) and print it (ctrl-p).
This tool is useful for viewing the output of code.
To get one, drag one out of the "Tools" flap
or select World...open...transcript.
To send output to it, enter
"Transcript show: expression
" in a Workspace
and do it.
This is basically equivalent to System.out.print
in Java.
To add a carriage return and make it like System.out.println
,
enter "Transcript show: expression; cr
".
To clear the window, press ctrl-a to select everything and press delete
or enter "Transcript clear
".
When more than one Transcript window is open, output goes to all of them.
The Smalltalk equivalent of Java's toString
method,
which returns the string represenation of an object,
is the printString
method.
This is invoked when a "print it" is performed on an object.
A new, labelled Transcript window can be opened from code.
ts := TranscriptStream new. ts open. "opens window with default title of Transcript". ts openLabel: 'My Transcript'. "opens window with custom title" ts show: 'Hello'
For simple cases, this can be combined on one line as
"TranscriptStream new open; show: 'some message'
".
Transcript
is a global variable that refers to a
TranscriptStream
.
Another option for displaying small amounts of output is to use
"self inform: some-string
"
which displays a string in a dialog.
A "browser" allows viewing and editing of classes and methods. One way to open a browser is to open the "Tools" flap and drag out a "System Browser". Another way is to enter "class-name browse" in a Workspace and "do it" by pressing ctrl-d.
Classes are grouped in categories. Methods within classes are grouped in protocols. Common protocols include "accessing", "adding", "comparing", "converting", "copying", "displaying", "enumerating", "formatting", "instance creation", "printing", "removing" and "testing". The System Browser has four panes across the top for categories, classes, protocols and methods. The bottom pane, called the "edit pane", is for browsing, editing and adding classes and methods.
To select a category, click on it's name in the category pane. To scroll closer to it, click in the cagtegory pane and type the first letter.
The buttons at the bottom of the class pane control what is displayed in other panes. Press the "instance" button to display instance methods in the method pane. Press the "class" button to display class methods in the method pane. Press the "?" button to see the comment for the selected class in the edit pane.
To move a method to another protocol, drag its name from the method pane to its new protocol in the protocol pane.
The buttons above the edit pane control what is displayed in other windows. To display a Hierarchy Browser for the current class, double-click it in the class pane or select it in the class pane and press the "hierarchy" button or ctrl-h. This displays all superclasses and subclasses of the current class. Unlike the System Browser, this tool allows browsing all the classes in the inheritance hierarchy of a given class in a single window. Another way to see the superclasses and subclasses of a given class is to enter "Class-Name printHierarchy" in a Workspace and "print it" (ctrl-p).
The last button at the top of the edit pane defaults to "source". To enable pretty printing (formatting) of the code that happens automatically when changes are saved, press the "source" button and select "pretty print" or "color print".
When a method is selected so that its code is displayed in the edit pane, to view its class definition in the edit pane, yellow-click the method to deselect it.
In a Squeak-Dev image it defaults to using "OB Package Browser" in place of "System Browser". This is also known as the "OmniBrowser".
Unlike the System Browser, this has back (<<) and forward (>>) buttons just above the editor pane for moving between recently browsed classes.
In the editor pane, by default it automatically outputs matching characters as you type for single quotes, double quotes, parentheses, square brackets, and so on. If you find this annoying, it can be disabled. On the World menu, select "Preferences & Services"..."Preference Browser". Select the "developer image" category. Disable ecompletionSmartCharacters.
Icons in front of method names provide extra information. For a description of what they mean, see http://smallwiki.unibe.ch/hermion/icons/.
It get hints on issues with code, yellow-click a category, class or method and select open...code critics.
To find all the references to a given instance or class variable within a class, yellow-click the class in OmniBrowser and select an option from the open environment submenu such as class variable references, instance variable reader, instance variable references, and instance variable writer.
An Inspector is used to examine the variables in a given object.
Select a variable in the upper-left pane to
display its value in the upper-right pane.
The value in the upper-right pane can be modified.
After changing it, press ctrl-s to save the change.
The lower pane is used to enter code can be executed.
For example, when inspecting a Dictionary object the code
self at: 'foo' put: 'bar'
can be entered.
To execute this, select the code and press ctrl-d (do it).
This tool is useful for viewing the output of code. To get one, drag one out of the "Tools" flap or select World...open...method finder. Enter part of a method name and press enter to get a list of all method names that contain it. Click a method name in the list to see the class that defines it.
To find all messages containing the selected string, press ctrl-W.
To find the methods that send a given message, select the message in a browser or enter it in a Workspace and press alt-n. This is a great way to find example uses of a message.
To find the classes that implement a given message, select the message in a browser or enter it in a Workspace and press alt-m.
When no text is selected, these commands operate on the entire current line.
To browse a class in a new System Browser, select its name in any window and press ctrl-b. To use the same System Browser, press ctrl-B. To choose from a list of recently browsed classes, yellow-click in the category pane and select "recent classes" or press ctrl-r.
To print the result of the last statement in the Workspace, press ctrl-p or yellow-click and select "print it". The output will be selected. Press the delete key to delete it.
To inspect the result of the last statement in an Inspector dialog, press ctrl-i or yellow-click and select "inspect it". This shows the class of the result in the title bar and allows all instance variables of the object to be examined.
To execute the statements without printing, press ctrl-d or yellow-click and select "do it".
Packages are Smalltalk applications and libraries that can be downloaded and installed in your image. One way to download new packages or upgrade existig packages is to press "Package Universe Browser" button on the desktop. Another way is to open the "Tools" flap and drag out a SqueakMap "Package Loader".
In the Package Universe Browser, press the "update list from network" button to get a list of available packages. For each package to be installed, click its name in the left pane and press the "select package" button. After all the selections have been made, press the "Install Selections" button at the bottom. Press the "select all upgrades" button to select upgrades to all currently installed packages.
In the SqueakMap Package Loader, red-click a category in the lower-left pane to limit the packages displayed in the upper-left pane. Red-click a package name in the upper-left pane to see a description of it in the right pane. Yellow-click a package in the upper-right pane and select "Install" to install it.
Another tool to examine is Monticello.
To create a new category, yellow-click in the category pane of a System Browser and select "add item...".
To create a new class, red-click its category in a System Browser. This will display a template for the new class in the bottom pane with the following content:
Object subclass: #NameOfSubclass instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'category-name'
This creates a new class by sending a message to its superclass.
Modify the base class if necessary (defaults to Object
)
and change "NameOfSubclass" to the name of the new class as a symbol.
Add names of instance variables, class variables and pool dictionaries.
Press ctrl-s to save it.
The class will be given a comment of "THIS CLASS HAS NO COMMENT!".
Change that to a better comment and press ctrl-s again.
Classes are represented by objects from the Class
class
that are referred to by a global variable with the same name as the class.
Select the class in the class pane of a System Browser and press ctrl-x or yellow-click the class name and select "remove class".
To find a class in a System Browser when you don't know what category it is in, click in the category pane and press ctrl-f or yellow-click in the category pane and select "find class...". Enter all or part of the name. Select the class from the list of matching classes. It's category will be highlighted in the category pane and also shown in the class definition after "category:".
To browse a class that has been browsed recently, yellow-click in the category pane and select "recent classes...".
To browse a class whose name is selected in the bottom pane of a System Browser, press ctrl-b.
To create an object from a class named "Foo"
and assign it to a variable,
use "foo := Foo new.
".
This invokes the new
method in the
Class
object for the Foo
class.
The Class
class is a subclass of the
Behavior
class which defines the new
method.
That calls basicNew
and initialize
.
If the class has an instance initialize
method,
it will be invoked.
This is a good place to initialize instance variables to default values.
In most cases, the first thing an initialize method should do is
send the initialize message to its superclass with
super initialize
.
If data must be specified in order to properly construct new objects, write class methods that accept the data, create a new instance, and initialize it with the supplied data. For example:
create: total "creates a new Math instance with a given starting value for total" ^self new total: total; yourself
This can be invoked as follows:
"m := Math create: 3.
".
There are five ways, involving four classes, in which objects can be
created without using the new
method.
String
-
'text'
Point
-
x@y
BlockClosure
-
[ statements ]
Array
-
#( element1 element2 ... )
Array
-
{ expression1. expression2. ... }
All of these involve syntax that the compiler must recognize except
@
which is a binary method in the Number
class.
The last two that create arrays are specific to Squeak.
To browse or edit an existing method in a System Browser:
The code will be displayed in the edit pane.
To add a method to a class, select the class in a System Browser, press either the "instance" or "class" button depending on the method type, select the protocol for the method (may need to add a new one), modify the code template for the method in the bottom pane, and press ctrl-s to compile it to bytecode and save it.
Here's an example of a class method in a class named "Math". It uses keyword parameters "add" and "and". It uses a temporary variable named "sum". It returns a value (^). Note the lack of a period at the end of the last line.
add: n1 and: n2 "adds two numbers" | sum | sum := n1 + n2. ^sum
Here's an example of some instance method in a class named "Math".
initialize "initializes a new Math object" total := 0 total "retrieves the running total" ^total add: value "adds value to the running total" total := total + value
To delete a method, yellow-click its name in the method pane of a System Browser and select "remove method".
Method arguments cannot have default values. To simulate this, create overloaded methods where those that take fewer parameters call those that take more with default values for their missing parameters.
To format the code of the method being viewed in a browser, yellow-click and select "pretty print".
The class that controls pretty print is RBFormatter
.
It can be customized. For example,
the method maxArgumentsPerLine
defaults to 1 which
causes each keyword in a keyword message to be on a separate line.
Consider changing this to 5.
TODO: How does this work?
One way to prompt the user for input is to use the FillInTheBlank class.
For example,
name := FillInTheBlank request: 'Enter your name'
.
The code for a class can be saved to a text file, possibly edited outside the Squeak enviroment, and read back in. To save the code for a class to a text file, yellow-click the class in a System Browser class pane and select "fileout". A file with the same name as the class and a ".st" file extension will be written to the directory containing the currently running image. To read in a text file containing code for a class, open the "Tools" flap, drag out a "File List", select the file, and press the "filein" button in the upper-right corner.
The preferred framework for implementating unit tests is
SUnit.
Create classes that inherit from TestCase
.
In the protocol "running", add setUp
and
tearDown
methods if needed.
In the protocol "tests", add methods that begin with "test".
In the test methods,
use "self assert: (boolean-expression)
"
and "self deny: (boolean-expression)
"
to specify assertions.
For testing exceptions there are should:raise:
and shouldnt:raise:
methods.
All of these assertion methods take an optional
description:
argument.
When an assertion fails, it's description string is displayed in the
title bar of the window that is displayed when a failed test is selected.
The description strings are also displayed in the Transcript window
if the test case overrides the isLogging
method
to return true
.
To run the tests, open the Tools flap and drag out an "SUnit Runner". Select the categories and test classes to be run. Press the "Run Selected" button. If all the tests pass, the bar in the upper-right will be green. If test failures occur, the bar will be yellow and the test methods with failures will be listed in the right-middle panel. If errors are encountered, the bar will be red and the test methods with errors will be listed in the right-bottom panel. Clicking on the name of a test method with a failure or error will display a window containing a stack trace (referred to as a "walkback stack") for the method.
In OmniBrowser, all the tests in a category can be run by yellow-clicking a category in the category pane and selecting "run the tests" or pressing ctrl-t. A summary of the results is displayed in a dialog, but details are not displayed in a "Test Runner" window.
To set breakpoints, add "self halt.
" statements in the code.
When a breakpoint is hit, a debugger window will be displayed.
It allows inspection and modification of
instance and local/temporary variables.
Source code can be viewed and modified in the debugger.
It also provide buttons for controlling continued execution
such as Into (step into a message send), Over (step over a message send),
Through (step into a block), Proceed (close debugger and continue)
and Restart (go back to beginning of current method).
In OmniBrowser,
methods containing a call to "self halt.
"
will have a red flag icon in front of them in the method pane.
To debug code in a Workspace, select the code, yellow-click and select "debug it".
This tool is a distributed versioning system. It is the primary means in which Squeak developers backup and distribute their code. To open a Monticello Browser, drag one out of the Tools flap or select World...open...Monticello Browser.
To backup a package locally, select it in the left pane, select the "package-cache" directory in the right pane, and press the "Save" button. This will create a .mcz file which is a Monticello zip file containing the code for the package (snapshot/source.st) and a few other files.
To save a package on SqueakSource:
To retrieve a package from SqueakSource:
There are many refactoring options available in browsers. Yellow-click a class in the class pane or a method in the method pane and select an item from the refactor submenus.
To change the fonts used in the Squeak environment, open the World menu and select appearance...system fonts... Fonts used in existing windows won't be changed. To see new fonts, close the windows and open new ones. A good font is Accujen size 10 or 12. To install additional True Type fonts (.ttf files), download them, open a File List tool, select a .ttf file, and press the "install ttf" button.
SVI is a text editor for Squeak that supports Vim and Emacs commands. It is used in place of the default PluggableTextMorph. To install it, open a World menu, select open...SqueakMap Package Loader, open the SVI tree node, yellow-click the version you want, and select "install. This didn't work! I'm trying to find a solution.
Squeak projects are like separate working environments, each with its own set of open windows on the desktop ... like virtual desktops. The can be used to separate work on different projects, or separate work on difference aspects of the same project (such as model classes vs. view classes). They can improve coding efficiency because switching between projects is faster than opening or expanding Browsers.
On the World menu there are items to create a new project ("open...morphic project"), switch to the previous project ("previous project"), switch to a selected project ("jump to project..."), save a project to a file ("save project on file...") and load a project from a file ("load project from file..."). The main or default project is named "New Changes".
After creating a new project, give it a name by changing the text at the bottom of the mini project window icon.
Projects are saved in ".pr" files. When saved locally, they are in the Squeaklets subdirectory of the current image.
Projects can be nested.
Morphic is a library for building Squeak GUIs.
A "morph" is similar to a widget in other GUI toolkits.
Supplied morphs include
CheckboxMorph
,
DropDownChoiceMorph
,
DropListMorph
,
ImageMorph
,
LabelMorph
,
MenuItemMorph
,
MovieMorph
,
ProgressBarMorph
,
SimpleButtonMorph
,
TextFieldMorph
and
TreeListMorph
.
All the morphs visible on the desktop are submorphs of the "world" morph.
The mouse cursor is referred to as the "hand" and
it is an instance of HandMorph
.
Here's a simple example of creating a button that when pressed displays text in a Transcript window.
button := PluggableButtonMorph on: [Transcript show: 'You pressed it!'; cr] getState: nil action: #value. button label: 'Press Me!'. button position: 100@100; openInWorld
Morph layout can be done automatically or
it can be controlled by layout morphs.
The most commonly used of these is AlignmentMorph
which arranges morphs from left to right in a single row
or from top to bottom in a single column.
The AlignmentMorph
newSpacer:
method
adds space between morphs.
User interations with morphs are represented by
MorphicEvent
objects.
When mouse and keyboard events occur, messages such as
mouseDown
, mouseMove
, mouseUp
and keyStroke
are sent to morph objects.
If a morph is dropped on another morph, the target morph is asked
whether it can handle the dropped morph by sending the message
wantsDroppedMorph: aMorph event: evt
to it.
If this returns true then the message
wantsDroppedMorph: aMorph event: evt
is sent to it.
After the target processes the drop, the source of the drop will be sent
the message justDroppedInto: aMorph event: evt
.
To determine the class of a morph that is currently displayed,
blue-click to get the halo, press the "debug" button (the wrench),
and select "browse morph class".
Windows are created using the SystemWindow
class.
Select "explore morph" to see the "submorphs".
For more inforamation, see An Introduction to Morphic.
There are many alternatives to Morphic. These include Polymorphic, Tweak and wxSqueak.
When a Squeak image starts up,
it calls the class startUp
method in each class listed
in the collection referred to by the SystemDictionary
class variable StartUpList
.
When a Squeak image shuts down,
it calls the class shutDown
method in each class listed
in the collection referred to by the SystemDictionary
class variable ShutDownList
.
The SystemDictionary
class initialize method
adds many classes to these lists.
The only instance of SystemDictionary
is held
in the global variable Smalltalk
.
Classes are added to these lists by sending the messages
addToStartUpList
and addToShutDownList
to Smalltalk
.
Classes are removed from these lists by sending the messages
removeFromStartUpList
and removeFromShutDownList
to Smalltalk
.
To see what is currently in these lists, view the class definition
of SystemDictionary
in a browser, select the class variable
StartUpList
or ShutDownList
,
and press ctrl-I to "explore it".
In some cases it's important for the order of classes in these lists
to be opposite of each other.
Under Mac OS X, to make "squeak" available as a command,
open a Terminal window and cd to any directory in your PATH.
Create a symbolic link by entering
"ln -s "$SQUEAK_VM_DIR/Squeakversion.app/Contents/MacOS/Squeak VM Opt" squeak".
When Squeak is started from a Terminal window using this command
it doesn't run properly. It doesn't respond to mouse events
and the -headless
option doesn't work!
To run a Smalltalk script without starting the GUI,
create a text file with a ".st
" file extension,
add a sequence of Smalltalk statements in it, and
run "squeak -headless $SQUEAK_IMAGE full-file-path.st
".
Here's an example of such a script. Note that temporary variables don't need to be declared.
"The file is written in the directory of the image." fs := FileStream fileNamed: 'FileIODemo.txt'. fs nextPutAll: 'line 1'; cr. fs nextPutAll: 'line 2'. fs close.
This runs the script, but there are two issues. First, a splash screen is displayed. To prevent this, rename or delete the "splash.bmp" file in the Squeak VM directory. Second, the VM doesn't exit automatically. To make it exit when the script finishes, add the following line to the end of the script.
SmalltalkImage current quitPrimitive
There are many ways to implement persistence in Smalltalk including ActiveRecord (from Cincom), GLORP, GOODS, Gemstone/S, ImageSegments, Magma, OmniBase, PostgreSQL, Prevayler, ReferenceStreams, Roe, SIXX, SQLite, and simply saving the image.
FFI is used to call functions that are typically implemented in C.
The remaining information either needs to be merged with the information above or deleted.
SystemDictionary addToStartUpList: class-name.
The class is required to understand the #startUp:
message,
which will be sent to it when the image is loaded and started.
#startUp:
accepts a Boolean telling it
whether the image is resuming (newly started).
Also see
How to lockdown an image for release.
From Matthew Fulmer: When you run code, it is compiled into a method called UndefinedObject>>DoIt, then that method is run, then deleted. The source code of that method is the code you run. It happens when running a doit from the workspace, or when filing-in code. Squeak version control is automatic! (describe this)
Copyright © 2008 Object Computing, Inc. All rights reserved.