The Smalltalk Image
While other languages lose some utility when divorced from their associated libraries, portions of Smalltalk simply evaporate. Traditionally, however, Smalltalk marries its class library, the language processors, and the development tools into a single entity called the image. The Squeak virtual machine is a platform-independent byte-code interpreter not unlike the VMs that come with more recently developed languages such as Java. The image, however, doesn't have an analogue with other languages--it is a platform-independent snapshot of the current state of the VM's object memory. The VM along with an image becomes, in effect, a "virtual workstation." Each time you restart a Squeak VM with a given image, your entire context reloads from exactly where you left off. This means that the stack trace you were looking at when you exited the image will still be there when you get back--even if you restart the image on another VM on another architecture.
Typically, you start with the base image as it comes from squeak.org and customize it to suit your goals and objectives. As distributed, the image contains objects implementing fundamental building blocks of the language (
Dictionary, etc.), GUI frameworks, and development tools (which are really just objects that provide UIs for editing, debugging, variable inspections and so on). Ultimately, a Squeak program is a VM and an image customized to provide a particular user experience when started.
Starting Squeak with a particular image differs from platform to platform. After installing Squeak on Ubuntu, simply typing
squeak at a shell prompt (or starting Squeak from the
Development menu) will, if necessary, create a ~/squeak directory and copy in the base image. You'll then be able select any image in that directory to start. When you've done so, you will have the chance to update your image. Saying "yes" will query squeak.org for updates and apply them. Typically with the stable images supplied with various distributions, there are no updates to apply.
Click the background of the main Squeak window. In the resulting menu that appears, select
Save As... and save the image as experiment.image. Now, should you desire, you'll always be able to get back to a fresh image. It's not unusual for a Squeak developer to have numerous images saved. Some will be configured for different purposes (web deployment versus development, for example). Others might be snapshots saved before undertaking a particularly risky bit of refactoring.
Figure 1. The Workspace in Squeak
Now, click the Squeak desktop again. In the world menu, select
Open... and, from the resulting menu, select
Workspace. In a Squeak image, the Workspace (Figure 1) serves roughly the same purpose as a command prompt in other development environments. It is not, however, a Read-Eval-Print-Loop such as found with Lisp or Python. Rather, it is simply an editable scratch space that does some variable management for you. By highlighting text in a work space you can execute it by pressing
Alt-P (for Print It, which evaluates the code and prints the result) or
D (for Do It, which just evaluates the result). Type
1 + 5.
into the workspace, highlight it, and print it. The number 6 will print.
Developing in Smalltalk
To get a feel for development in an image, create a new class. Imagine that you're writing a program that, among other things, generates
cron entries. For now, your class will concentrate on converting day names into the ordinal numbers expected by
cron and will store the associated command. Type this code into the workspace and do it:
Object subclass: #CronGen instanceVariableNames: 'command' classVariableNames: 'DayMap' poolDictionaries: '' category: 'Example-Category'.
This creates a new class,
CronGen, with a member variable,
command, and a class variable,
DayMap. In Smalltalk, classes are instances of the type
Class. Note in this example how creating a class in a Smalltalk image differs from other languages. In Java or Ruby, you'd enter source code into a text editor, save it, and then let the language system process it. The class would be created in the current runtime instance. In contrast, the Smalltalk example sends a message to an already existing instance of the type
Object. That message returns another instance of the type
Class, called CronGen in this case. Unless it is removed, this instance,
CronGen, will continue to exist in the image it was created in. Smalltalkers refer to this as working with "live" objects.
This may seem like a distinction without a difference at first, but it has a rather profound effect on the language. Enter this code in the workspace and Do it:
Figure 2. The Smalltalk browser
This will open a classic Smalltalk browser (Figure 2). The panels along the top represent class categories, classes, message categories, and messages, respectively. Class categories are a way of grouping related classes into applications or packages. Highlighting a category causes the class panel to only show classes in that category. Highlighting a class lists only the message categories of that class in the message category panel, and so on.
You've probably seen similar tools in other language IDEs. There is an important difference, however. Browsers for other languages must work by parsing the source code for the language in some way, generally manipulating text files. Often, the parser used by the development tools is not the same as the language compiler, with all of the perils of redundancy that implies. Smalltalk development tools, on the other hand, can work by introspection. The browser simply iterates over the image's collection of classes and then introspects the resulting class objects to create the browser's view. In a Smalltalk image, code really is data.