Discuss Scratch
- Discussion Forums
- » Show and Tell
- » SAPLING (programming language) - tutorial
- skies_shaper
-
Scratcher
31 posts
SAPLING (programming language) - tutorial
SAPLING tutorial
SAPLING version: 1.4
project link: https://scratch.mit.edu/projects/884272995/
code-sharing forum link: https://scratch.mit.edu/discuss/topic/735404/
Most recent update notes: https://scratch.mit.edu/projects/958248931/
Hi! This is a slightly more readable of the tutorial I made for SAPLING a while back.
Introduction
SAPLING is an advanced, interpreted language run in Scratch 3. It has numerous capabilities that run past those of Scratch on its own, while retaining Scratch’s simplicity of use.
To understand SAPLING, you might need to know a little bit about another programming language (javascript, python, java), to understand everything.
SAPLING basics
A normal line of code will be broken up into two parts:
A command (“println”), and an input (“hello, world!”). A line of code will have a command, followed by any number of inputs separated by commas.
Part 1: Getting started
To begin, go to the main SAPLING project (https://scratch.mit.edu/projects/884272995). Press the green flag. This will always bring the project to the main menu. On the main menu, you can see a button with a plus sign. Press it to create a new program. New programs will have the text
written in them. These two lines of code are SAPLING’s header.Every SAPLING program will start with
a filename followed by a colon
an initial program type declaration
We’ll talk about what you can do with each of those lines later, but for now, all you need to know is that a program with “@console” as line 2 will print out text.
Controls-wise, in Turbowarp, this functions as a normal text editor would, however in Scratch there is a costume to take place of the ‘delete’ key. In the upper-middle of the screen is green text reading “run”. Press that to run a program.
Basic commands
println(input)
This will print the given input to the console, followed by a new line.
print(input)
This will print the given input to the console, without a new line following it.
wait(number)
This will pause the program from running for a given number of seconds.
input(input)
This prints out input, then allows the user to type in a response. To access the user’s response, call the ‘response()’ function:
broadcast(input)
broadcastandwait(input)
These both do the same as the scratch blocks
playsound(sound)
startsound(sound)
These both do essentially the same as the
endprog(input)
This will end your program entirely. The Scratch variable
Note that a program will stop on its own when any function declarations are reached, unless otherwise specified.
Control flow
SAPLING’s control flow functionality is more or less the same as Scratch’s. It has for loops, if statements and while loops.
repeat (10)
…
end
works the same in scratch as
works in SAPLING.
For if statements,
works the same in Scratch as
works in SAPLING
SAPLING does not have a repeat until loop, though. Instead it uses a while loop. These are quite similar, however.
works in SAPLING.
Inputs
SAPLING can handle 4 different things as an argument into a function:
1) A string:
These are surrounded with double quotes (“”) and can include the following escape characters:
“\n”: This will add a newline to the string.
“\\”: This will add a backslash (\) to the string.
“\””: This will add a double-quote (“) to the string
“\c######”: this will set the console’s color to the RGB value of ######.
“\[variable]”: This will insert variable at this point in the string.
“\@##”: this will add the ##th character in my character encoding to the string (see the
2) A number:
Any number (not including weird things like 10e+35)
3) A variable:
All variables are surrounded in square brackets:
4)A function:
SAPLING built-in functions
These are more or less backwards-compatible with Scratch.
SAPLING has
-username()
-mouseX()
-mouseY()
-timer()
-response(): the previous answer to the input() command
-posof(char,string): returns the first index of the given character in the given string
-substring(string, index1, index2): returns the part of the given string within the two boundaries inclusive
-do(input)
(returns input. This might seem useless, but you can’t use parentheses in math (no 1+(2*3)), so you’ll want to use this instead.)
-concat(input1, input2, …)
(acts like the
-random(number1, number2)
-length(input)
-round(number)
-floor(number)
-abs(number)
-sqrt(number)
-sin(number)
-cos(number)
-tan(number)
-asin(number)
-acos(number)
-atan(number)
-ln(number)
-log(number)
-epower(number)
-tenpower(number)
These should all work like they do in scratch
Booleans and Math
In SAPLING, you can do normal math like you would in a calculator:
However, there are a few caveats.
You can’t use parentheses for grouping, you must instead use the ‘do()’ function.
For boolean operators like and, or, equals, greater than and less than, you use the following characters:
& | = > <
To use the not operator, use
!(boolean)
If you want to use the values true and false, just type them as strings.
Variables
It is at long last time to learn how to utilize variables, data storage, and data structures in SAPLING! Yay!
To create a variable, type “var”, then variable names:
Set a variable to a value with the equals sign:
You can't do that on the same line as a variable declaration, however.
Incrementation, decrementation, etc works much the same as it does in Javascript:
Obejcts and Lists
In Scratch, you can make a list. This is a data structure that can hold as many numbers or strings as you want. But what if you wanted that list to hold other lists? In scratch, this is doable, but not out-of-the-box. In SAPLING, however, it's as easy as making any other variable a list! To make a list, take a variable and modify it with the .add() command
This will make ‘myList’, a list with one item (that item being 5)
You can continue to add items to ‘myList’ with the .add() command.
'But wait!' I hear you ask. ‘I want to set the first item of my list to 17, not 5!’. You can do that by setting the variable list_# to your value:
'But wait!' You cry out once more. ‘I want the list item I set to change!’ You can do that too! Just use the $() command.
will set the [i]th index of [myList] to 12.
This function stacks as well,
will set the [k]th index of the [j]th index of the [i]th index of [myList] to 12.
If you want to access a specific variable, you can do so in much the same way: Just use the $() function within a line of code;
Which will function the same as
To remove or insert specific list items, use
Which do essentially what they say (remove item index from list and insert value just after index index).
To find a list's length, use the [myList.length] variable.
To find whether or not a certain item is in a list, use the
function and to find the first index of a specific value in a list, use
Objects
Scratch doesn't have these, now does it?
For a crash course in objects, objects are variables (somewhat like lists) that store many different pieces of data. However, instead of accessing the 1st or 2nd or 17th item of the list, you access the ‘name’ field, or ‘age’ field of an object. Objects are useful when you want to store data with attributes. To make one, use the Object() function:
This makes the variable [person] have a name, age, and birthday field, accessible with the [person_name], [person_age], and [person_birthday] variables.
This is easier to remember than remembering which item of a list is someone's name, or age, or so forth.
If an object's field has ‘_’ characters in it, you will want to access it with the $() function, which works with objects as well.
Now. Let's take our [person] from the previous code example. And let's say you have another person, with the same attributes. What you would do, is make an new variable, and set it equal to [person].
This will give [bob] the attributes “name”, “age”, and “birthday”! This is called inheritance.
FUNctions
So. You have a lot of code. But it's disorganized and hard to read. So what do you do in Scratch? you put different parts of it that do different things into My Blocks. In SAPLING, you make functions. Let's take a look at an example Scratch My Block that adds two numbers:
You will notice that a function will be defined with the ‘function’ keyword, then have a function name ('addTwo') and inputs ('number1', ‘number2’) (These are optional)
A function ends with the ‘endf’ keyword combined with the function name.
So that's more or less the same as in Scratch. But when calling this, what do you have to do?
This is almost the same!
But! With the ‘return’ statement, you can then call this function within another function, and it will give the same outcome!
But that second method improves your code's length and readability, as well as the number of variables you have to deal with!
In addition, the ‘return’ statement will make your function end, instead of having to wait for the ‘endf…’ keyword.
Files
SAPLING has a reasonably advanced file system that allows you to save data between programs! This is useful, trust me. SAPLING variables aren't saved between program runs, but these are, and they show up on the main menu!
note: I'm not entirely satisfied with the file system though, it might change in the future
That being said, there are 5 file-manipulation functions:
These do the following things:
- writefile(file): given a file, add the given text to it.
- openfile(file, startline, endline): this will open the given file (optionally starting at startline or starting at startline and ending at endline).
- deletefile(file): This removes the given file from the file system. Use it carefully!
- createfile(file): This creates a file with the given name.
- run(file): This runs the given file as a SAPLING program.
Important! THE RUN COMMAND MAY NOT PROPERLY WORK DEPENDING ON YOUR PROGRAM. USE IT AT YOUR OWN RISK
SpriteControl
This is SAPLING's pride and joy (sorta). With SpriteControl, you can freely merge your SAPLING and Scratch programs, commanding your Scratch sprites from one central SAPLING program.
Let's take a look.
To use a SpriteControl command, simply
1) set a variable equal to the sprite() function, with the input being the value of the target sprite's
Then, at any time, use a colon after that variable's name to make it do the command before the parenthesis:
The previous example would cause the
SAPLING modes and pre-interpreter statements
You may have noticed that every single program starts with ‘@console’. You may have found yourself asking “why? Is it just to look cool?”, and the answer is no. You see, my friend (for I hope that this far into the tutorial, we have become friends), this second line can be one of three things:
These are Pre-Interpreter Instruction Tags (which I shall get to in a moment), but more specifically, they are your Program Type Declaration. They will tell the interpreter what your program is.
-@console: This is a console program, which will have basic text interactivity
-@graphics: You are on your own for rendering, SAPLING will not print anything out or display anything except for signaling when complete.
-@library: This is a collection of functions that will not be run.
other Pre-interpreter Statements
Libraries
This is SAPLING's solution to using other people's functions! Unlike the run() statement, these should work. Which is nice!
To make your code a library, use the @library Pre-interpreter statement a the beginning of the program. That's it!
You can also add a function to be run at the beginning of a user who has loaded your library's program with the following syntax: myLibrary.sapi:init().
Let's take a look:
Now, to actually use these libraries, you need the import keyword:
Event-driven programming
Scratch is an event-driven language. You have your
First, use the @event-driven pre-interpreter statement.
What this does, is it makes the interpreter continue to be active when your program finishes, only stopping your program with an endprog() command.
Additionally, no code in the main body of the program will be run, only in the main() function which you provide.
Let's check out a basic program like this:
But that's a little boring. So, let's introduce a way to interact with events!
-onevent(event,function): This will run the specified function name (string) when an event event is received.
-trigger(event,data): This will cause the specified event to be added to the event stack.
That's nice and all, but now you might be asking yourself: how can I get an event?
You just need to, in your scratch project, have a little script that can be as simple as this:
Now let's make some SAPLING code to go along with that.
Note you can also pass data through this. The first argument of a function called through events will always be filled with the item added to
If you don't add something to one of the lists, the events cache will be cleared, removing all events you may have saved up.
Remember: events are worked through one-at-a-time in the order they are recieved.
Let's look at a more complicated event example. In the ‘blank’ sprite of the main SAPLING project, there is a set of blocks disconnected from a
Connect them, and then try the following program:
SAPLING version: 1.4
project link: https://scratch.mit.edu/projects/884272995/
code-sharing forum link: https://scratch.mit.edu/discuss/topic/735404/
Most recent update notes: https://scratch.mit.edu/projects/958248931/
Hi! This is a slightly more readable of the tutorial I made for SAPLING a while back.
Introduction
SAPLING is an advanced, interpreted language run in Scratch 3. It has numerous capabilities that run past those of Scratch on its own, while retaining Scratch’s simplicity of use.
To understand SAPLING, you might need to know a little bit about another programming language (javascript, python, java), to understand everything.
SAPLING basics
A normal line of code will be broken up into two parts:
println("hello, world!")
Part 1: Getting started
To begin, go to the main SAPLING project (https://scratch.mit.edu/projects/884272995). Press the green flag. This will always bring the project to the main menu. On the main menu, you can see a button with a plus sign. Press it to create a new program. New programs will have the text
myprogram.sapi: @console
a filename followed by a colon
an initial program type declaration
We’ll talk about what you can do with each of those lines later, but for now, all you need to know is that a program with “@console” as line 2 will print out text.
Controls-wise, in Turbowarp, this functions as a normal text editor would, however in Scratch there is a costume to take place of the ‘delete’ key. In the upper-middle of the screen is green text reading “run”. Press that to run a program.
Basic commands
println(input)
This will print the given input to the console, followed by a new line.
print(input)
This will print the given input to the console, without a new line following it.
wait(number)
This will pause the program from running for a given number of seconds.
input(input)
This prints out input, then allows the user to type in a response. To access the user’s response, call the ‘response()’ function:
println(response())
broadcastandwait(input)
These both do the same as the scratch blocks
broadcast [ v](except they can't do certain broadcasts, such as the ones SAPLING itself uses, in order not to cause weird errors )
broadcast [ v] and wait
playsound(sound)
startsound(sound)
These both do essentially the same as the
play sound [ v] until doneblocks
play sound [ v]
endprog(input)
This will end your program entirely. The Scratch variable
(SAPLING-RESTRICTED: GLOBAL RETURN)will be set to input, if it is provided.
Note that a program will stop on its own when any function declarations are reached, unless otherwise specified.
Control flow
SAPLING’s control flow functionality is more or less the same as Scratch’s. It has for loops, if statements and while loops.
repeat (10)
…
end
works the same in scratch as
for(10) //… end
For if statements,
if <> then
…
end
works the same in Scratch as
if(somethingIsTrue()) //… end
SAPLING does not have a repeat until loop, though. Instead it uses a while loop. These are quite similar, however.
repeat until <not<something happens>>works much the same as
…
end
while(somethingIsTrue()) //… end
Inputs
SAPLING can handle 4 different things as an argument into a function:
1) A string:
These are surrounded with double quotes (“”) and can include the following escape characters:
“\n”: This will add a newline to the string.
“\\”: This will add a backslash (\) to the string.
“\””: This will add a double-quote (“) to the string
“\c######”: this will set the console’s color to the RGB value of ######.
“\[variable]”: This will insert variable at this point in the string.
“\@##”: this will add the ##th character in my character encoding to the string (see the
(chars::list)list in the ‘blank’ sprite in the project.)
2) A number:
Any number (not including weird things like 10e+35)
3) A variable:
All variables are surrounded in square brackets:
[myVariable]
println(myFunction())
These are more or less backwards-compatible with Scratch.
SAPLING has
-username()
-mouseX()
-mouseY()
-timer()
-response(): the previous answer to the input() command
-posof(char,string): returns the first index of the given character in the given string
-substring(string, index1, index2): returns the part of the given string within the two boundaries inclusive
-do(input)
(returns input. This might seem useless, but you can’t use parentheses in math (no 1+(2*3)), so you’ll want to use this instead.)
-concat(input1, input2, …)
(acts like the
(join()())block, can have as many inputs as you want)
-random(number1, number2)
-length(input)
-round(number)
-floor(number)
-abs(number)
-sqrt(number)
-sin(number)
-cos(number)
-tan(number)
-asin(number)
-acos(number)
-atan(number)
-ln(number)
-log(number)
-epower(number)
-tenpower(number)
These should all work like they do in scratch
Booleans and Math
In SAPLING, you can do normal math like you would in a calculator:
println(1+2*3/5%6)
You can’t use parentheses for grouping, you must instead use the ‘do()’ function.
For boolean operators like and, or, equals, greater than and less than, you use the following characters:
& | = > <
To use the not operator, use
!(boolean)
If you want to use the values true and false, just type them as strings.
Variables
It is at long last time to learn how to utilize variables, data storage, and data structures in SAPLING! Yay!
To create a variable, type “var”, then variable names:
var x, y, z, myVariable
myVariable = 17
Incrementation, decrementation, etc works much the same as it does in Javascript:
myvar++ myvar-- myvar+=5 myvar-=5 myvar*=5 myvar/=5 myvar%=5
In Scratch, you can make a list. This is a data structure that can hold as many numbers or strings as you want. But what if you wanted that list to hold other lists? In scratch, this is doable, but not out-of-the-box. In SAPLING, however, it's as easy as making any other variable a list! To make a list, take a variable and modify it with the .add() command
var myList myList.add(5)
You can continue to add items to ‘myList’ with the .add() command.
'But wait!' I hear you ask. ‘I want to set the first item of my list to 17, not 5!’. You can do that by setting the variable list_# to your value:
myList_1 = 17
$("myList",[i],12)
This function stacks as well,
$("myList",[i],[j],[k],12)
If you want to access a specific variable, you can do so in much the same way: Just use the $() function within a line of code;
println($("myList",7))
println([mylist_7])
myList.remove(index) and myList.insert(index, value)
To find a list's length, use the [myList.length] variable.
To find whether or not a certain item is in a list, use the
contains(listname, value)
indexOf(listname, value)
Scratch doesn't have these, now does it?
For a crash course in objects, objects are variables (somewhat like lists) that store many different pieces of data. However, instead of accessing the 1st or 2nd or 17th item of the list, you access the ‘name’ field, or ‘age’ field of an object. Objects are useful when you want to store data with attributes. To make one, use the Object() function:
var person person = Object("name", "age", "birthday")
This is easier to remember than remembering which item of a list is someone's name, or age, or so forth.
If an object's field has ‘_’ characters in it, you will want to access it with the $() function, which works with objects as well.
Now. Let's take our [person] from the previous code example. And let's say you have another person, with the same attributes. What you would do, is make an new variable, and set it equal to [person].
bob = [person]
FUNctions
So. You have a lot of code. But it's disorganized and hard to read. So what do you do in Scratch? you put different parts of it that do different things into My Blocks. In SAPLING, you make functions. Let's take a look at an example Scratch My Block that adds two numbers:
define addTwo (number 1) (number 2)How would we port that to SAPLING?
set [result v] to ((number 1) + (number 2))
function addTwo(number1, number2) result = number1+number2 endfaddTwo
A function ends with the ‘endf’ keyword combined with the function name.
So that's more or less the same as in Scratch. But when calling this, what do you have to do?
addTwo(1) (2) ::customThat's perhaps a bit too much code. It makes sense, but most modern programming languages have a workaround: the ‘return’ statement. Let's look to see how that would work in SAPLING:
say(result)
function addTwoWithReturn(number1, number2) return(number1+number2) endfaddTwoWithReturn
But! With the ‘return’ statement, you can then call this function within another function, and it will give the same outcome!
addTwo(1,2) println([result]) //is the same as println(addTwoWithReturn(1,2)) function addTwo(number1, number2) result = number1+number2 endfaddTwo function addTwoWithReturn(number1, number2) return(number1+number2) endfaddTwoWithReturn
In addition, the ‘return’ statement will make your function end, instead of having to wait for the ‘endf…’ keyword.
Files
SAPLING has a reasonably advanced file system that allows you to save data between programs! This is useful, trust me. SAPLING variables aren't saved between program runs, but these are, and they show up on the main menu!
note: I'm not entirely satisfied with the file system though, it might change in the future
That being said, there are 5 file-manipulation functions:
writefile(file,text) openfile(file,startline,endline) deletefile(file) createfile(file) run(file)
- writefile(file): given a file, add the given text to it.
- openfile(file, startline, endline): this will open the given file (optionally starting at startline or starting at startline and ending at endline).
- deletefile(file): This removes the given file from the file system. Use it carefully!
- createfile(file): This creates a file with the given name.
- run(file): This runs the given file as a SAPLING program.
Important! THE RUN COMMAND MAY NOT PROPERLY WORK DEPENDING ON YOUR PROGRAM. USE IT AT YOUR OWN RISK
SpriteControl
This is SAPLING's pride and joy (sorta). With SpriteControl, you can freely merge your SAPLING and Scratch programs, commanding your Scratch sprites from one central SAPLING program.
Let's take a look.
var scratchCat scratchCat = sprite("scratchcat") scratchCat:say("welcome to SAPLING!")
1) set a variable equal to the sprite() function, with the input being the value of the target sprite's
(sprite-control ID)variable.
Then, at any time, use a colon after that variable's name to make it do the command before the parenthesis:
The previous example would cause the
say [welcome to SAPLING]block to execute.
SAPLING modes and pre-interpreter statements
You may have noticed that every single program starts with ‘@console’. You may have found yourself asking “why? Is it just to look cool?”, and the answer is no. You see, my friend (for I hope that this far into the tutorial, we have become friends), this second line can be one of three things:
@console @library @graphics
-@console: This is a console program, which will have basic text interactivity
-@graphics: You are on your own for rendering, SAPLING will not print anything out or display anything except for signaling when complete.
-@library: This is a collection of functions that will not be run.
other Pre-interpreter Statements
@event-driven //This will make the program use events (see later in the tutorial)
This is SAPLING's solution to using other people's functions! Unlike the run() statement, these should work. Which is nice!
To make your code a library, use the @library Pre-interpreter statement a the beginning of the program. That's it!
You can also add a function to be run at the beginning of a user who has loaded your library's program with the following syntax: myLibrary.sapi:init().
Let's take a look:
myLibrary.sapi: @library function myLibrary.sapi:init() println("this code is running from a library!") endfmyLibrary.sapi:init //add more functions here as you see fit.
import myLibrary.sapi //the rest of your program
Scratch is an event-driven language. You have your
when I receive [broadcast v]your
when [space v] key pressedand your
when green flag clickedblocks. SAPLING doesn't have these, out of the box in a basic program. But integrating them with SAPLING is a breeze!
First, use the @event-driven pre-interpreter statement.
What this does, is it makes the interpreter continue to be active when your program finishes, only stopping your program with an endprog() command.
Additionally, no code in the main body of the program will be run, only in the main() function which you provide.
Let's check out a basic program like this:
myEventdrivenProgram.sapi: @console //note you still have to specify as a console program @event-driven //this can be put anywhere function main() println("awaiting events!") endfmain
-onevent(event,function): This will run the specified function name (string) when an event event is received.
-trigger(event,data): This will cause the specified event to be added to the event stack.
That's nice and all, but now you might be asking yourself: how can I get an event?
You just need to, in your scratch project, have a little script that can be as simple as this:
when [space v] key pressedThis will add an event to the event stack, along with some data associated with that event.
add [] to [EVENTS-data v]
add [space key pressed] to [EVENTS v]
Now let's make some SAPLING code to go along with that.
myEventdrivenProgram.sapi: @console @event-driven function main() println("You haven't pressed the space key yet") onevent("space key pressed","myFunction") endfmain function myFunction() println("you pressed the space key!") endfmyFunction
(EVENTS-data :: list)with your event.
If you don't add something to one of the lists, the events cache will be cleared, removing all events you may have saved up.
Remember: events are worked through one-at-a-time in the order they are recieved.
Let's look at a more complicated event example. In the ‘blank’ sprite of the main SAPLING project, there is a set of blocks disconnected from a
when [any v] key pressedblock.
Connect them, and then try the following program:
mySuperEventdrivenProgram.sapi: @console @event-driven function main() println("You haven't pressed any key yet") onevent("keypress","onKeyPressedFunction") endfmain function onKeyPressedFunction() println("you pressed the space key!") endfmyFunction
Last edited by skies_shaper (Jan. 30, 2024 03:31:44)
- skies_shaper
-
Scratcher
31 posts
SAPLING (programming language) - tutorial
This is just going to be reserved for things like updates and so forth.
- skies_shaper
-
Scratcher
31 posts
SAPLING (programming language) - tutorial
Wow!Thanks! It's kinda long haha
- skies_shaper
-
Scratcher
31 posts
SAPLING (programming language) - tutorial
This is just a general announcement that this has new content now! I added a few things I had forgotten about, and also there's a new function! (see update notes)
- Discussion Forums
- » Show and Tell
-
» SAPLING (programming language) - tutorial