Squeak Tutorial

SandCastleIcon.png This page has links to outside of the Scratch website or to Wikipedia. Always remember to be safe when using the internet since we can't guarantee the safety of other sites.
Archive.png This article or section documents a feature not included in the current version of Scratch (2.0). It is only useful from a historical perspective.

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.[1] 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.

Warning Note: In this tutorial, the format multipleWordsWithoutSpaces is used a lot. This is standard programming practice to represent many words without spaces, and is called camel case.

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:

Argument Scratch symbol Panther symbol Description
String %s $String$ Accepts any characters
Number %n $Number$ Accepts numbers, periods, commas, and the negative sign (-)
Boolean %b $Boolean$ Accepts boolean (diamond) blocks
Sprite %m $Sprite$ A dropdown with a list of sprites
Variable %v $Variable$ A dropdown with a list of variables
Attributes %a $Attributes$ A dropdown with a list of attributes (direction etc.)
Color picker %C $Color$ A color picker with a popout pallet
Color picker %c $ScreenColor$ A color picker without a popout pallet
Directions %d $Directions$ A dropdown with a list of directions
Drums %D $Drums$ A dropdown with a list of drum sounds
Events %e $Event$ A dropdown with a list of broadcasts
Math functions %f $MathFunctions$ A dropdown with a list of math functions (abs, sin etc.)
Effects %g $Effects$ A dropdown list of effects such as color and brightness
Sensors %h $SensorNames$ A dropdown list of sensor names such as slider (for a PicoBoard)
Sensor booleans %H $SensorBooleans$ A dropdown list of PicoBoard booleans such as "A connected?"
Instruments %I $Instruments$ A dropdown list of instruments
List options %i $ListIndex$ A dropdown of list indexes (1, last, any)
Key options %K $Keys$ A dropdown list of keyboard keys
Lists %L $List$ A dropdown list of lists
Costumes %l $Costumes$ A dropdown list of costumes
Motors %W $MotorNames$ A dropdown list for the Motor Blocks
Notes %N $Notes$ A note space with popout keyboard
Sounds %S $SoundNames$ A dropdown list of sounds

Block shapes

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

- Stack The shape of a Stack Block.png
b Boolean The shape of a Boolean block.png
r Reporter The shape of a Reporter Block.png
c Loop The shape of one of the C blocks.png
g Color (Panther (Scratch Modification) only) The Shape of a Color Panther Block.png
t Timed block These blocks have the authorization to pause a script for some time, evaluating a command. Examples: Wait () secs, Play note () for () beats
s Special form For example, if/else has two "c" inputs. These need special code.

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
| aTemp |
someCode

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 Methodname:argument moreOfName:moreArguments. So Make _ cups of tea looks like this: makeCupsOfTea:amount.

Warning Note: You cannot have method names after the last argument, so Make:amount cups of tea is prohibited.

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 variable _ value.

Warning Note: In the Squeak editor, the underscore is depicted as an arrow facing left (←).

Example:

modifyAVariable
| aVar |
aVar _ 10

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: 'hi' 'bye'.

To represent a single quote within a string, use two single quotes in a row: 'my clock''s ticking'.

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

'Hello, ', 'John, ', ' what''s ', 'up?' "Hello John, what's up"

Note that a variable can be concatenated to a string: t1, '= 5'.

Methods Which Report Values

A method can report a value, as noted above. In Squeak, this is done with the syntax ^ value.

Warning Note: In the MIT Squeak editor, ^ becomes an arrow facing up (↑)

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:

[t1 _ 33 ^ 'hey, there']

In Squeak, there are many uses of conditional code. Here are some:

| t1 t2 |
t1 _ (1 = 0) "t1 contains the value true"
t2 _ (1 = 1) "t2 contains the value false"

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)
Warning Note: With the abstraction of first-class data, a class method can be thought of as an attribute set to a lambda (unnamed function).

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 subclass 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 (Mini Cooper) is called the Child or Subclass of the other class (Car), which is called the Parent or Superclass.

Morphs inherit from the Morph parent class. Morph inherits from Squeak's Object class. Object 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 NSObject. All other classes must inherit from either NSObject or a class which inherits from NSObject. Thus, NSString inherits from NSObject, and NSAttributedString inherits from NSString. 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 Car? Is it a subclass of Vehicle or the parent of Mini Cooper?

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, click—all--. 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 self, 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 |
myCopy := Car new.
myCopy color _ self color
myCopy driver _ self driver
^ myCopy

Now to copy a car, you can just say

myFamilyCarCopy _ myFamilyCar copy

Morphic Classes

Morphic classes define Morphs. To create a Morph, a subclass of Morph, rather than the root class Object is used. Here is the class definition (create a category called My-Morphs)

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 drawOn: 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.
A block without an existing method running out of fill screen mode.


In the System Browser, syntax errors can not be accepted.
A syntax error in Squeak.

External Links

References

  1. https://scratch.mit.edu/discuss/topic/115258/
  • This page was last modified on 12 February 2016, at 03:50.