Code Execution#
The SuperCollider IDE iis designed for interactivity. If you’re familiar with the concept of notebooks, such as Jupyter or Mathematica notebooks, you’ll grasp what I mean. The idea is to execute code incrementally as you develop. Instead of writing a complete program all at once, you’re encouraged to run small code snippets. Each code execution alters your environment, that is, the state of your program. This dynamic interaction is especially evident in live coding, but it’s also a useful practice when learning and exploring SuperCollider in general.
SuperCollider initializes an Environment, which is a collection of entities accessible by name. Interacting with the IDE allows you to manipulate this environment in real-time.”
Triggering the Evaluation#
Let’s get started!
We’ll write some sclang
code and execute it via the REPL (Read-Eval-Print Loop).
To execute the following line, press SHIFT
+ RETURN
while your cursor is on the code line.
"Hello World!".postln;
In SuperCollider, as there is no use of code cells, we must define blocks of code ourselves.
To execute multiple lines, we need to enclose the code within brackets (
and )
, then evaluate the code using CMD
+ RETURN
on Mac or CTRL
+ RETURN
on Windows.
Code Execution
Use SHIFT
+ RETURN
to evaluate a single line of code and use CMD
+ RETURN
to evaluate a code block.
For example:
(
"Hello World!".postln;
"We make some music".postln;
)
In both scenarios, you’ll observe that the last line appears twice in the post window. SuperCollider always prints the last statement in the post window.
As in any other object-oriented language, we call a method named postln
on an object that represents a String.
However, different terminology is used in the SuperCollider documentation.
In this context, the object is the receiver of a message (method).
The object always functions as the first argument to the method (much like in Python
).
We refer to this object as this
.
For instance, we could also employ the following syntax:
postln("Hello World!");
A very useful hotkey is CMD
+ d
(Mac OS) or CTRL
+ d
(Windows).
It will open the documentation of the code your cursor is at.
Lookup Documentation
Use CMD
+ d
(Mac OS) or CTRL
+ d
(Windows) to look at the documentation of the class or method your cursor is at.
Execution of C++ Code#
Let’s reverse-engineer the process that occurs when we print a string to the post window.
Lookup Source Code
Use CMD
+ i
(Mac OS) or CTRL
+ i
to look at the actual implementation of the class or method your cursor is at.
If we look into the source code of the postln
method by using CMD
+ i
and navigate to the class Object
, we can digest the following implementation:
postln { this.asString.postln; }
The curly brackets define a function with the name postln
.
As mentioned, this
is either
the object the method is called on (if we use
"Hello World!".postln;
) orthe first argument of the method (if we use
postln("Hello World!");
)
Calling this.asString
transformes the object into a String
.
Then postln
of that String
is called.
Of course in our case, the object is already a String
and we directly call postln
of String
!
Let’s have a look at postln
of the class String
:
postln {
_PostLine
^this.primitiveFailed
}
This looks strange.
What is going on here?
Here we enter the C++
code.
_PostLine
is a primitive.
It is executed, and if nothing goes wrong, the code below (^this.primitiveFailed
) is not executed.
In the C++
file PyrPrimitive.cpp we find the following code snippet:
definePrimitive(base, index++, "_PostLine", prPostLine, 1, 0);
and prPostLine
is a method:
int prPostLine(struct VMGlobals* g, int numArgsPushed) {
PyrSlot* a;
a = g->sp;
// if (NotObj(a)) return errWrongType;
// assume it is a string!
postText(slotRawString(a)->s, slotRawString(a)->size);
postChar('\n');
return errNone;
}
In the documentation, we find the following explanation
g->sp
is the top of the stack and the last argument pushed.g->sp - inNumArgsPushed + 1
is the receiver and where the result goes.
In our case, g->sp
is the String object.
This interaction between sclang
and C++
reminds me of the interaction between Python
and C++
.
As long as we do not write our own primitives, we can ignore the C++
interaction.
Order of Execution#
In sclang
, the code is strictly evaluated from left to right.
All operands have the same priority, which might lead to unexpected results.
The expression
4 + 4 * 5 // 40
returns (4 + 4) * 5 = 40
instead of 4 + (4 * 5) = 24
.
Order of Execution
sclang
uses a strictly left to right order of execution.
Especially within control structures this can lead to bugs that are hard to find.
The following code prints 'ho'
to the the post window.
(
// true || false => true && false => false
if(true || false && false,{
"hi".postln;
}, {
"ho".postln;
})
)
The following two statements are equivalent:
a = 5; b = 7; c = 12;
a * (b+c);
b + c * a;