Eng:Squeak Tutorial

Smalltalk had been used in Scratch since the first version of Scratch was released in 2007 until the release of Scratch 2.0 in 2013. Using a Squeak virtual-machine (VM) by MIT slightly edited to meet Scratch's needs, Smalltalk is the coding language that creates the Scratch world, blocks, sprites, and everything the Scratcher sees when they use the application. Recently there has been an influx of users who want to get into the Scratch browser and tinker with the source code, and a whole host of Scratch Modifications have sprung up as a result. These modifications sometimes allow users to edit Smalltalk as part of their features, such as Panther, where users can create their own blocks using a Smalltalk window. With this sudden craze of modifying Scratch, a great many guides and questions have been posted all over the Advanced Topics teaching various aspects of editing Scratch and using Smalltalk. This Smalltalk "library" allows all the creators of these guides to pool their resources and compile a large collection of easy to understand tutorials in using Smalltalk within the Scratch VM.

How a Scratch block comes to be
A good way to introduce Squeak to a Scratcher is to explain how to make blocks. A block consists of two parts: the blockspec and the method. A blockspec defines the block: it tells Scratch what the block is and does. The method explains to Scratch how to do what it does. It is similar to a table of contents. The blockspec is what Scratch looks up, and the method is the page it finds, which it reads.

The blockspec itself consists of three parts: the title, which is the text displayed on the block, the type, which is the shape of the block (reporter, predicate, cap, stack, c-shaped, timed, or special form), and the method selector, which is like the page number: it tells Scratch which code the block should evaluate.

The title is a formatted string, which is a string of a particular format. For example, the strings "Hi56", "Bye813", and "Pi_is_3.14159" all follow the pattern Text+Number. In a block, the formats describe the inputs of our blocks, called arguments. For example, "%s %n" describes a block with a String input (text box) and a numerical input (text box that accepts just numbers, decimal points, and the negative sign (-)). Arguments are covered in detail in the following section.

Getting to the blocks' display
To get to the blocks' display, or blockSpecs, first shift-click the R in the Scratch Logo in Scratch 1.4 and Turn fill screen off. Then click in the white space and on the menu that pops up select Open. Then select Browser on the next menu that pops up. A giant yellow box should pop up. On the list of things in the top left corner of the box, select Scratch-Objects which should be first in the list. Then select either ScratchSpriteMorph or ScratchStageMorph in the list centered-left at the top of the box. Now below that list, click Class. Then select block specs, the only one in the list centered-right, and then select blockSpecs in the rightmost list.

Arguments
In Scratch, blockspec titles are formatted with %a, %b, etc. for arguments. However, in a popular modification Panther, a title is formatted with $something$. This allows any number of characters in the formatted argument (note how since Scratch needs %+a symbol, only 26*2=52 types of arguments can be made). Here's a list of commonly used arguments that can be put in a block followed by the format code for Scratch and Panther and a description:

Block shapes
The next part of a blockspec defines the block shape. This is added with a  symbol. Here are the shapes:

Methods
A method is a function, such as "Make a cup of tea". A method can have arguments, such as "Make _ cups of tea". They can also return a value, such as "Amount of sugar in _ cups of tea". A Squeak application runs on basically a collection of methods.

In Squeak, a method runs on three parts: the method selector, the temporary definitions, and the code. It looks like this: aMethod someCode
 * aTemp |

Before continuing, it is important to note that in Squeak, a comment is enclosed in double quotes ("). Comments are unevaluated code which tell us what is happening, for example: self beep "make some noise!" It is considered good programming practice to give an explanation of the method (and credits, etc.) in a comment right below the method selector.

Methods can have arguments. In Squeak, an argument is provided in a method with the syntax. So Make _ cups of tea looks like this:.

Temporary Variables
Temporary variables are called "temps". They are variables the method can use within itself but are not visible or usable anywhere else.

Temporary variables are listed below the method selector (see previous section) between two pipes (|). They are restricted to alphabets and numbers, and cannot be reserved (i.e., self).

It is conventional to name them t1, t2, t3, etc., but not necessary; in fact it is better to name them something legible. However, the Squeak compiler always converts temporary and input variables (arguments) to t1, t2 format.

Variable Modification
A variable is modified with the syntax.

Example: modifyAVariable aVar _ 10
 * aVar |

Strings
Strings are data; pieces of text which are not evaluated, but reported as they are. In Squeak, strings are represented within single quotes, examples:.

To represent a single quote within a string, use two single quotes in a row:.

To concatenate (join) strings, enumerate them separated by commas:

Note that a variable can be concatenated to a string:.

Methods Which Report Values
A method can report a value, as noted above. In Squeak, this is done with the syntax.

Example: report:aValue ^ aValue

Conditional Code
Square brackets are used for conditional code. Conditional code is similar to the hole in a C-shaped Scratch block like the If Then block  it may or may not be evaluated, or may be run many times. It is just code which the program can do anything with.

Conditional code is written like normal code, but in square brackets:

In Squeak, there are many uses of conditional code. Here are some: t1 _ (1 = 0) "t1 contains the value true" t2 _ (1 = 1) "t2 contains the value false"
 * t1 t2 |

t1 ifTrue: [^1]. "report 1 if t1 is true" t1 ifFalse: [^2]. "report 2 if t1 is false" t1 ifNotNil: [^3]. "report 3 if t1 is not nothing" 3 timesRepeat: [t1 _ t2]. "set t1 to t2 three times"

Classes and Instances
A class is a collection of
 * Methods
 * Attributes or properties (pieces of data unique to each class)

There are two kinds of classes: static classes and dynamic classes. A static class is just a collection of methods which can be run.

Dynamic Classes
A dynamic class is more interesting. A dynamic class represents an object. For example, the class "car" could represent a car. You can then create instances of these dynamic classes and set them to variables. For example, you can set "Mini Cooper" to a "car".

Dynamic classes include methods, so you can control them, for example, you can send the "car" object a "drive" method. They also have properties or attributes, which are pieces of data unique to the class. For example, the "car" class has the "color" attribute. Of course, attributes can be classes in themselves. For example, a "Mini Cooper" class can have a "car" class as an attribute.

However, an attribute of a class "x" cannot be an instance of the class "x", because the compiler will have to go in an infinite loop to keep initialize the classes.

Another important thing about dynamic classes is the copying protocol. When you set a variable to an instance of dynamic class, you do not create a copy of the dynamic class. You create a reference to the class, which when edited (say an attribute incremented), also affects the original instance. Thus, classes should provide a copying protocol, a method which returns a copy of itself by actually assembling the copy attribute by attribute. A copying protocol example will be given in a following section.

Inheritance
Every class inherits from another. An inherited class, called a  is given all the class variables and methods of the parent class. For example, if "Mini Cooper" inherits from "Car", the "Car" class can define the "Color" attribute, and all Cars will not need to define their colors separately.

The class which inherits is called the Child or Subclass of the other class, which is called the Parent or Superclass.

Morphs inherit from the  parent class. inherits from Squeak's  class. is the root class. All high-level languages provide a root class which is blank, with only atoms as attributes. All classes are (directly or indirectly) subclasses of the Root Class. For example, in Objective-C, the root class is. All other classes must inherit from either  or a class which  inherits from. Thus,  inherits from , and   inherits from. The inheritance is depicted with colons. Inheritance is shown right to left: NSAttributedString : NSString : NSObject NSOpenGLView : NSView : NSObject

Prototyping
Imagine the following inheritance model: Mini Cooper : Car : Vehicle : Object What is ? Is it a subclass of  or the parent of  ?

The answer is, both. In other words, every class can be visualized as its parent's child or its children's parent. This model of inheritance is known as Prototyping. In BYOB, the sprite-object-model is based on prototyping.

In Squeak
In Squeak, a class coding is extremely similar to natural language. In fact, Squeak is known as the most natural programming language.

Creating a Dynamic Class
First, open up the System Browser. Above the scroll bar in the list on the left side, click on the button with the dash (-) on it. Then select "add item...". When prompted, type in the name of the category to which your class belongs. A category can have many classes, like vehicles can have car and helicopter. For this tutorial, name it "Vehicles".

In the editing pane, you should have this code: Object subclass: #NameOfClass instanceVariableNames: 'instVarName1 instVarName2' classVariableNames: 'ClassVarName1 ClassVarName2' poolDictionaries: '' category: 'vehicles' Replace it with this. Read the annotations carefully. Object subclass: #Car "Class name" instanceVariableNames: 'driver' 'color' "attributes" classVariableNames: '' "ignore for now" poolDictionaries: '' "ignore for now" category: 'vehicles' "category name" You have created the class! The class name is "Car", the attributes (Instance variables) are "driver" and "color", and category is "vehicles".

Now alt-click on the pane and select "accept". If prompted, type in your initials.

Next, we will add a simple method. Click on "Car" in the list second from the left in the System Browser. In the next list, clickall--. In the editing pane, you will get a sample method: message selector and argument names "comment stating purpose of message"

| temporary variable names | statements Highlight all of it, and replace it with this: drive Transcript show: 'Vroom!' Again, alt-click and select accept.

Now open the World Menu. Select open... >> Transcript. The transcript is a log where programs in Squeak can log values for debugging purposes.

Also open up a Workspace. A Workspace is a simple terminal to evaluate Squeak code. Type in the following code to test your now class: t1 := Car new. "Set t1 to a new Car" t1 drive "Drive the new car" "This code will be explained in the next section" Alt-click and select "do it."

In the transcript, you should see the text "Vroom!". This indicates the car was successfully created.

Using a Dynamic Class
Instances are created with the "new" command: myFamilyCar := Car new. Class methods or attributes are called with the syntax: class method class attribute myFamilyCar color _ 'black' myFamilyCar driver _ 'Dad' carcolor _ myCar color myFamilyCar drive

In Squeak, all classes are provided with a special constant called, which a reference to itself. If you, for example, need a method in the "Car" class which sets its color, you would reference the self object: setMyColor:aColor self color _ aColor

A copying protocol can then be written as follows: copy myCopy := Car new. myCopy color _ self color myCopy driver _ self driver ^ myCopy Now to copy a car, you can just say myFamilyCarCopy _ myFamilyCar copy
 * myCopy |

Morphic Classes
Morphic classes define Morphs. To create a Morph, a subclass of, rather than the root class   is used. Here is the class definition (create a category called ) Morph subclass: #MyMorph instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'My-Morphs' This morph can already be drawn, with the following code (in a Workspace): MyMorph new openInWorld. This renders a blank blue rectangle.

A more interesting Morph can be created by implementing the  method: drawOn: aCanvas | acolor | acolor := Color random. "get a random color" aCanvas fillOval: (self bounds) color: acolor "draw something" Morphs can react to events, such as clicks. Two methods are required: one to listen for clicks and one to act on the event: handlesMouseDown: evt ^ true "listen" mouseDown: evt self position: self position + (0@10) Morphs can also be animated. Here, three methods are required: startAnimation "initialization" self startStepping stepTime "speed, in milliseconds" ^75 step "how to move" self position: self position + (1@1)

Of course, to use a morph efficiently, it must be assigned to a variable, or it will not be editable. To assign a Morph to a variable, the variable is assigned its initialization: t1 := aMorph new openInWorld.

Syntax Errors
When an error occurs in a script, if you are not in fill screen mode, Squeak displays popups instead of the block turning red.

In the System Browser, syntax errors can not be accepted.