Catalog of symbolic notations in SuperCollider
Arithmetic operators
Math operators apply to many classes, including arrays and other collections.
Using a basic math operator on a Symbol swallows the operation (returns the symbol)
\symbol * 5
symbol
number + number addition
number - number subtraction
number * number multiplication
number / number division
number % number modulo
number ** number exponentiation
Bitwise arithmetic
number & number bitwise and
number | number bitwise or
number << number bitwise left shift
number >> number bitwise right shift
number +>> number unsigned bitwise right shift
Logical operators
object == object equivalence
object === object identity
object != object not equal to
object !== object not identical to
Objects may be equivalent but not identical.
[1, 2, 3] == [1, 2, 3]
true
[1, 2, 3] === [1, 2, 3]
false // a and b are two different array instances with the same contents
a = b = [1, 2, 3];
a === b;
true // a and b are the same array instance
number < number comparison (less than)
number <= number comparison (less than or equal to)
number > number comparison (greater than)
number >= number comparison (greater than or equal to)
Boolean && Boolean logical And
Boolean || Boolean logical Or
When a function is the second operand, these operators perform short-circuiting (i.e., the function is executed only when its result would influence the result of the operation). This is recommended for speed.
With and: and or: second-argument functions will be inlined. If you use && or ||, no inlining will be done and performance will be slower.
a = 1;
a == 1 and: { "second condition".postln; [true, false].choose }
second condition
true
a == 1 or: { "second condition".postln; [true, false].choose }
true
a != 1 and: { "second condition".postln; [true, false].choose }
false
a != 1 or: { "second condition".postln; [true, false].choose }
second condition
true
In this case, the second condition will cause an error if a is nil, because nil does not understand addition. a.notNil is a safeguard to ensure the second condition makes sense.
a = nil;
a.notNil and: { "second condition".postln; (a = a+1) < 5 }
false
a = 10;
a.notNil and: { "second condition".postln; (a = a+1) < 5 }
second condition
false
Array and Collection operators
object ++ object concatenation
collection +++ collection lamination (see J_concepts_in_SC)
collection @ index collection/array indexing: .at(index) or [index]
collection @@ integer collection/array indexing: .wrapAt(int)
collection @|@ integer collection/array indexing: .foldAt(int)
collection |@| integer collection/array indexing: .clipAt(int)
Set operators
set & set intersection of two sets
set | set union of two sets
setA - setB difference of sets (elements of setA not found in setB)
set -- set symmetric difference
(setA -- setB) == ((setA - setB) | (setB - setA))
a = Set[2, 3, 4, 5, 6, 7];
b = Set[5, 6, 7, 8, 9];
a - b
Set[ 2, 4, 3 ]
b - a
Set[ 8, 9 ]
((a-b) | (b-a))
Set[ 2, 9, 3, 4, 8 ]
a -- b
Set[ 2, 9, 3, 4, 8 ]
Geometry operators
number @ number x @ y returns Point(x, y)
point @ point Point(left, top) @ Point(right, bottom)
returns Rect(left, top, right-left, bottom-top)
ugen @ ugen create a Point with 2 UGens
rect & rect intersection of two rectangles
rect | rect union of two rectangles (returns a Rect
whose boundaries exactly encompass both Rects)
IOStream operators
stream << object represent the object as a string and add to the stream
A common usage is with the Post class, to write output to the post window.
Post << "Here is a random number: " << 20.rand << ".\n";
Here is a random number: 13.
stream <<* collection add each item of the collection to the stream
Post << [0, 1, 2, 3]
[ 0, 1, 2, 3 ]
Post <<* [0, 1, 2, 3]
0, 1, 2, 3
stream <<< object add the object's compile string to the stream
Post <<< "a string"
"a string"
stream <<<* collection add each item's compile string to the stream
Conditional execution operators
object ? object nil check (no .value)
object ?? function nil check (.value, function is inlined)
If the object is nil, the second expression's value will be used; otherwise, it will be the first object.
a = [nil, 5];
10.do({ (a.choose ? 20.rand).postln });
10.do({ (a.choose ?? { 20.rand }).postln });
?? { } is generally recommended. ? always evaluates the second expression, even if its value will not be used. ?? evaluates the function conditionally (only when needed). If the function defines no variables, the function will be inlined for speed.
Especially useful when the absence of an object requires a new object to be created. In this example, it's critical that a new SCSlider not be created if the object was already passed in.
f = { |slider, parent|
slider = slider ?? { SCSlider.new(parent, Rect(0, 0, 100, 20)) };
slider.value_(0);
};
If the first line inside the function instead read slider = slider ? SCSlider.new(parent, Rect(0, 0, 100, 20));, a new slider would be created even if it is not needed, or used.
object !? function execute function if object is not nil
a = [10, nil].choose;
a !? { "ran func".postln };
// equivalent of:
if (a.notNil) { "ran func".postln };
Used when an operation requires a variable not to be empty.
f = { |a| a + 5 };
f.value
// error: nil does not understand +
f = { |a| a !? { a+5 } };
f.value
nil // no error
f.value(2)
7
Miscellaneous operators
object ! number object.dup(number)
15 ! 5
[ 15, 15, 15, 15, 15 ]
If the object is a function, it behaves like Array.fill(number, function).
{ 10.rand } ! 5
[ 8, 9, 3, 8, 0 ]
object -> object creates an Association, used in dictionaries
expression <! expression bypass value of second expression
This operator evaluates both expressions, and returns the value of the first.
a = 0;
0
// a is incremented twice, but the return value (1)
// comes from the first increment (0 + 1)
(a = a + 1) <! (a = a + 1)
1
a // a's value reflects both increments
2
function <> function function composition operator
This operator returns a new function, which evaluates the second function and passes the result to the first function.
f = { |a| a * 5 } <> {|a| a + 2 };
f.(10);
60 // == (10+2) * 5
An array as argument is passed through the chain:
f.([10, 75, 512]);
[ 60, 385, 2570 ] // == ([10, 75, 512]+2) * 5
Symbolic notations to define literals/other objects
$ character prefix: "ABC".at(0) == $A
'' or \ define a literal Symbol: 'abc' === \abc
"" define a literal String
[item, item...] define an Array containing given items
Set[item, item...] define a Set -- any Collection class name can be used other than Set
#[item, item...] define a literal Array
(a:1, b:2) define an Event (same as Event[\a -> 1, \b -> 2])
` (backtick or backquote) define a Ref: `1 == Ref(1), `(a+1) == Ref(a+1)
\ inside a string or symbol, escapes the next character
"abc\"def\"ghi"
abc"def"ghi
'abc\'def\'ghi'
abc'def'ghi
\t tab character
\n newline character
\l linefeed character
\r carriage return character
\\ \ character
{ } define an open function
#{ } define a closed function
(_ * 2) define a function { |a| a * 2 } (see Partial-Application)
Argument definition
|a, b, c| define function/method arguments
|a, b ... c| define function/method arguments;
arguments after a and b will be placed into c as an array
#a, b, c = myArray assign consecutive elements of myArray to multiple variables
#a, b ... c = myArray assign first two elements to a and b; the rest as an array into c
Where f is a function
f.( ) evaluate the function with the arguments in parentheses
f.(*argList) evaluate the function with the arguments in an array
f.(anArgName: value) keyword addressing of function or method arguments
f = { |a, b| a * b };
f.(2, 4);
f.(*[2, 4]);
f.(a: 2, b: 4);
SomeClass.[index] Equivalent to SomeClass.at(index) -- Instr.at is a good example
myObject.method(*array) call the method with the arguments in an array
obj1 method: obj2 same as obj1.method(obj2) or method(obj1, obj2)
This works only with single-argument methods
like binary operators.
Class and instance variable access
Inside a class definition (see Writing-Classes):
classvar <a, Define a class variable with a getter method (for outside access)
>b, Define a class variable with a setter method
<>c; Define a class variable with both a getter and setter method
var <a, Define an instance variable with a getter method (for outside access)
>b, Define an instance variable with a setter method
<>c; Define an instance variable with both a getter and setter method
These notations do not apply to variables defined within methods.
^someExpression Inside a method definition: return the expression's value to the caller
instVar_ { } define a setter for an instance variable
myObject.instVar = x; invoke the setter: (myObject.instVar_(x); x)
Array series and indexing
(a..b) produces an array consisting of consecutive integers from a to b
(a, b..c) e.g.: (1, 3..9) produces [1, 3, 5, 7, 9]
(..b) produces an array 0 through b
(a..) not legal (no endpoint given)
a[i..j] a.copyRange(i, j)
a[i, j..k] e.g.: a[1, 3..9] retrieves array elements 1, 3, 5, 7, 9
a[..j] a.copyRange(0, j)
a[j..] a.copyRange(i, a.size-1) (this is OK--Array is finite)
~ access an environment variable
~abc compiles to \abc.envirGet
~abc = value compiles to \abc.envirPut(value)
Adverbs to math operators (see Adverbs)
e.g.:
[1, 2, 3] * [2, 3, 4]
[ 2, 6, 12 ]
[1, 2, 3] *.t [2, 3, 4]
[ [ 2, 3, 4 ], [ 4, 6, 8 ], [ 6, 9, 12 ] ]
.s output length is the shorter of the two arrays
.f use folded indexing instead of wrapped indexing
.t table-style
.x cross (like table, except that the results of each operation
are concatenated, not added as another dimension)
.0 operator depth (see J_concepts_in_SC)
.1 etc.