|This page has links to websites or programs not trusted by Scratch or hosted by Wikipedia. Remember to stay safe while using the Internet, as we can't guarantee the safety of other websites.|
|This article or section documents something not included in the current version of Scratch (3.0). It is only useful from a historical perspective.|
Many Scratchers wanted to get into the Scratch browser and tinker with the source code, and a whole host of modifications sprang up as a result. These modifications sometimes allow users to edit Squeak code as part of their features, such as Panther, where users can create their own blocks using Squeak. 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 Squeak. This Squeak "library" allows all the creators of these guides to pool their resources and compile a large collection of easy to understand tutorials in using Squeak to modify Scratch.
|Note:||In this tutorial, the format multipleWordsWithoutSpaces is used a lot. This is standard Smalltalk practice to write many words without spaces, and is called camel case.|
- 1 How a Scratch block comes to be
- 2 Finding the block specs
- 3 Expressions, objects, and messages
- 4 Methods
- 5 Strings
- 6 Blocks
- 7 Classes and instances
- 8 Errors
- 9 See Also
- 10 External Links
- 11 Notes
How a Scratch block comes to be
A block consists of two parts: the block specification and the method. The block spec tells Scratch how the block should appear and what it should do. It has four parts: the title, which contains the text of the block label along with its argument specifications; the block type, which is a symbol indicating what kind of block (stack, reporter, predicate, etc.) it should be; the message selector, which tells Scratch what code the block must run; and any default arguments. (An argument is a block input.) The method is the sequence of Smalltalk code the block runs.
- See also: Arguments#Scratch internals
In Scratch, an argument is added to a block spec title using a percent sign followed by a letter indicating the type of argument. For example, the block spec title of
move (10) steps is "move %n steps"; the "%n" indicates that the block should have a number argument. Here is a list of commonly used argument types, followed by the specification for Scratch and Panther and a description:[note 1]
|String||%s||$String$||Accepts any characters|
|Number||%n||$Number$||Accepts digits, decimal points, and the minus 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|
These are the block types:
|Color (Panther only)||g|
|Timed||t||These blocks do something over a given period of time. For example: Wait () Secs, Play Note () for () Beats|
|Special form||s||A special form is any block does not behave as an ordinary block does. For example, Wait Until () must repeatedly check its argument to find out whether or not it should stop; if it were an ordinary block, its argument would only be ran once.|
Each hat block has its own block type symbol, not listed here.
Finding the block specs
To find the block specs, first shift-click the R in the Scratch logo and select "turn fill screen off". Then click in the space that appears around Scratch to open the world menu and select "open…" followed by "browser". A large green window with four columns along the top and a large empty space below should pop up.
In the leftmost column, select "Scratch-Objects", which should be the first item. Then, if you want the block specs for both the stage and sprites, select "ScriptableScratchMorph"; if you want the block specs for the stage, select "ScratchStageMorph"; if you want the block specs for sprites, select "ScratchSpriteMorph". Now click "class", select "block specs" in the second column from the right, and select "blockSpecs" in the rightmost list.
Expressions, objects, and messages
Smalltalk code consists mostly of expressions. Each expression is evaluated to produce a value, or datum. The simplest kind of expression is called a literal expression; numerals and single-quoted strings are both literal expressions. For example,
42 is an expression whose value is the number 42.
Smalltalk is an object-oriented programming language. Every value in Smalltalk is an object; objects include numbers, strings, lists, blocks, the stage, and sprites. In OOP, rather than having a set of blocks to operate on data of each type (numbers and strings are two examples of types), the behavior becomes part of the data itself; objects communicate with each other by message passing. For example, the expression
((3) * (4)) in Scratch applies
(() * ()) to two arguments, both of which are numbers, and reports their product; but
3 * 4 in Smalltalk, on the other hand, sends a message to 3, the receiver, with two parts: the message selector, *, and an argument, 4. (The receiver and argument expressions may be expressions of any kind.)
A workspace is a window that may be used to evaluate expressions. To open a workspace, open the world menu, select "open…", and select "workspace". Then hover the mouse-pointer over the workspace, type an expression, right-click (on Microsoft Windows) or hold down Control and click (otherwise) on the workspace to bring up a context menu, and select "print it".
When 3 receives the * 4 message, it responds by finding the corresponding method, which answers with the product, 12. Methods are written in the wide area at the bottom of the System Browser. A method definition has three parts: the message selector, the temporary definitions, and the statements. It looks like this:
message selector and argument names "comment stating purpose of message" | temporary variable names | statements
Smalltalk, like Scratch, uses keyword arguments, meaning that the message selector is written combined with the argument expressions. (There are two exceptions to this: messages with no arguments and a few infix message selectors, like + and *.) Each part of the message selector is followed by a colon. For example, the message selector of
go to x: (0) y: (0) is "gotoX:y:". An argument expression should follow each colon, so it could be used as follows:
aSprite gotoX: 0 y: 0
In Smalltalk, a comment is enclosed in double quotation marks ("). Comments are not evaluated, but can be used to explain what is happening. It is considered good practice to give an explanation of the method (and credits, etc.) in a comment right below the message selector, if it is not clear.
The final part of a method definition is a sequence of statements, which is for the most part a sequence of expressions seperated by fullstops (with the exception given below).
Temporary variables are variables the method can use within itself but are not visible or usable anywhere else.
Temporary variables are listed below the message selector (see above) between two pipes (|). They are restricted to letters and digits, and cannot be reserved (i.e., "self").
If the Scratch Source Code is not present, you will see many names like t1, t2, t3, etc., but this is not necessary; it is almost always better to give variables self-descriptive names.
A variable, temporary or otherwise, is set using the syntax
variable _ value. (The new value is said to be assigned to the variable.) For example:
modifyAVariable | aVar | aVar _ 10
|Note:||In the Squeak editor, the underscore is depicted as an arrow pointing left (←). ":=" means the same as an underscore.|
A method can report a value, as the method for * does above. In Smalltalk, this is done by writing
^ value at the end of the method definition. For example:
report: aValue ^ aValue
|Note:||In the Squeak editor, "^" becomes an arrow pointing up (↑).|
A string is an object which represents some text. In Smalltalk, string literal expressions are written within single quotes, for example:
'hello'. To put a single quote in a string, use two single quotes in a row:
Strings are joined with a comma message:
'Hello, ', 'John, ', ' what''s ', 'up?' "Hello John, what's up?"
A block is similar to a C shape in Scratch — it may or may not be evaluated, or may be run many times. It is just code which the program can do anything with. Blocks are written like normal code, but in square brackets:
[t1 _ 33. ^ 'hey, there']
In Smalltalk, there are many uses of blocks. Here are some:
| t1 t2 | t1 _ (1 = 0). "t1 contains the value false" t2 _ (1 = 1). "t2 contains the value true" 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"
The Smalltalk messages ifTrue:, ifFalse:, etc. are not special: any message could have a block as an argument.
Classes and instances
In Smalltalk, types are represented by objects called classes; each object is an instance of a particular class. A class has a name; a set of instance variables, which are variables local to each instance of the class; and a set of instance methods, which are methods that define the behavior of its instances. For example, 6 is an instance of the class SmallInteger; when 6 is sent the * message, the corresponding instance method in SmallInteger is evaluated.
When an object is assigned to a variable, a copy of it is not created. The variable only stores a new pointer to the object, which may be used to send the object messages. For example, if the variable cat points to a sprite which is then assigned to aSprite, cat and aSprite both point to the same object, so if cat is rotated, aSprite will answer the new direction. Thus, classes should implement a copying protocol, a message which returns a copy of the object by actually assembling the copy attribute by attribute. A copying protocol example will be given in a following section.
Every class inherits from another. An inheriting class, called a subclass, is given all the variables and methods of the parent class. For example, if "Mini Cooper" is a class that inherits from "Car", the "Car" class could implement the "drive" message, and all Mini Coopers would be able to drive.
Morphs inherit from the
Morph parent class.
Morph inherits from Squeak's
Object is the root class. Most object-oriented programming languages provide a root class which is more or less blank. 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
NSString inherits from
NSAttributedString inherits from
NSString. The inheritance is depicted with colons. Inheritance is shown right to left:
NSAttributedString : NSString : NSObject NSOpenGLView : NSView : NSObject
In Squeak, the code of a class is extremely similar to natural language. In fact, Squeak is known as the most natural programming language.
Creating a class
First, open 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' classVariableNames: '' "ignore for now" poolDictionaries: '' "ignore for now" category: 'Vehicles'
You have created a class! The class name is "Car", the instance variables are driver and color, and category is "Vehicles".
Now right-click (on Microsoft Windows) or control-click (on Mac or another operating system) 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, right-click or control-click and select "accept".
Now open the world menu, select "open…", and select "transcript". The transcript is a log where programs in Squeak can log values for debugging purposes. Also open a workspace.
myFamilyCar _ Car new. myFamilyCar drive.
Right-click or control-click the workspace and select "accept". In the transcript, you should see the text "Vroom!"
Using a class
Instances are created by sending the class a "new" message:
myFamilyCar _ Car new.
Messages may be sent to the new instance with the syntax
object message. For example:
To be able to find or decide the color or driver of a car, it is necessary to write accessor methods and mutator methods. For example:
color ^ color driver ^ driver color: aColor color _ aColor driver: aDriver driver _ aDriver
These can be used like this:
myFamilyCar color: 'black'. myFamilyCar driver: 'Dad'. myFamilyCar color.
A copying protocol can be written as follows:
copy | myCopy | myCopy _ Car new. myCopy color: self color. myCopy driver: self driver. ^ myCopy
Self is a special variable in Smalltalk which references the object. (This allows the method for copy to send color and driver to the existing car; in this particular case it could be omitted because of the color and driver instance variables.) Now to copy a car, you can just say:
anotherFamilyCar _ myFamilyCar copy
Morphic classes define Morphs. To create a Morph, make a subclass of
Morph, rather than the root class
Object. 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
A blank blue rectangle will appear. A more interesting Morph can be created by implementing the drawOn: method:
drawOn: aCanvas "Draw a randomly colored oval." | aColor | aColor _ Color random. aCanvas fillOval: self bounds color: aColor
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 "Answer the period in milliseconds." ^ 75 step "Move slightly left and downwards." self position: self position + (1@1)
Of course, to use a morph effectively, it must be assigned to a variable, or it will not be editable. For example:
aMorph _ MyMorph new openInWorld
When an error occurs in a script, if you are not in fill screen mode, or have turned error catching off, Squeak displays popups instead of the block turning red.
In the System Browser, syntax errors can not be accepted.
- All About Squeak Smalltalk by Pecola1
- Reading Smalltalk, a guide for C++/Java programmers
- Bank Account Tutorial by John Maloney
- In Panther, an argument is added to a block title by writing the name of the argument type between dollar signs. This allows any number of argument types to be created, whereas in Scratch only 26×2 = 52 types of arguments can be made.
- All C blocks are also special forms, though they do not use s.