387 lines
13 KiB
Text
387 lines
13 KiB
Text
|
title:: Symbolic Notations
|
||
|
summary:: Catalog of symbolic notations in SuperCollider
|
||
|
categories:: Language
|
||
|
related:: Overviews/Operators, Reference/Syntax-Shortcuts
|
||
|
|
||
|
section:: 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)
|
||
|
code::
|
||
|
\symbol * 5
|
||
|
symbol
|
||
|
::
|
||
|
|
||
|
definitionlist::
|
||
|
## code:: number + number :: || addition
|
||
|
## code:: number - number :: || subtraction
|
||
|
## code:: number * number :: || multiplication
|
||
|
## code:: number / number :: || division
|
||
|
## code:: number % number :: || modulo
|
||
|
## code:: number ** number :: || exponentiation
|
||
|
::
|
||
|
|
||
|
section:: Bitwise arithmetic
|
||
|
definitionlist::
|
||
|
## code:: number & number :: || bitwise and
|
||
|
## code:: number | number :: || bitwise or
|
||
|
## code:: number << number :: || bitwise left shift
|
||
|
## code:: number >> number :: || bitwise right shift
|
||
|
## code:: number +>> number :: || unsigned bitwise right shift
|
||
|
::
|
||
|
|
||
|
section:: Logical operators
|
||
|
definitionlist::
|
||
|
## code:: object == object :: || equivalence
|
||
|
## code:: object === object :: || identity
|
||
|
## code:: object != object :: || not equal to
|
||
|
## code:: object !== object :: || not identical to
|
||
|
::
|
||
|
|
||
|
Objects may be equivalent but not identical.
|
||
|
code::
|
||
|
[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
|
||
|
::
|
||
|
|
||
|
definitionlist::
|
||
|
## code:: number < number :: || comparison (less than)
|
||
|
## code:: number <= number :: || comparison (less than or equal to)
|
||
|
## code:: number > number :: || comparison (greater than)
|
||
|
## code:: number >= number :: || comparison (greater than or equal to)
|
||
|
::
|
||
|
definitionlist::
|
||
|
## code:: boolean && boolean :: || logical And
|
||
|
## code:: 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 code:: and: :: and code:: or: :: second-argument functions will be inlined. If you use code::&&:: or code::||::, no inlining will be done and performance will be slower.
|
||
|
code::
|
||
|
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.
|
||
|
code::
|
||
|
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
|
||
|
::
|
||
|
|
||
|
section:: Array and Collection operators
|
||
|
|
||
|
definitionlist::
|
||
|
## code:: object ++ object :: || concatenation
|
||
|
## code:: collection +++ collection :: || lamination (see link::Guides/J-concepts-in-SC::)
|
||
|
## code:: collection @ index :: || collection/array indexing: .at(index) or [index]
|
||
|
## code:: collection @@ integer :: || collection/array indexing: .wrapAt(int)
|
||
|
## code:: collection @|@ integer :: || collection/array indexing: .foldAt(int)
|
||
|
## code:: collection |@| integer :: || collection/array indexing: .clipAt(int)
|
||
|
::
|
||
|
|
||
|
section:: Set operators
|
||
|
definitionlist::
|
||
|
## code:: set & set :: || intersection of two sets
|
||
|
## code:: set | set :: || union of two sets
|
||
|
## code:: setA - setB :: || difference of sets (elements of setA not found in setB)
|
||
|
## code:: set -- set :: || symmetric difference:
|
||
|
code::
|
||
|
(setA -- setB) == ((setA - setB) | (setB - setA))
|
||
|
::
|
||
|
::
|
||
|
|
||
|
code::
|
||
|
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 ]
|
||
|
::
|
||
|
|
||
|
section:: Geometry operators
|
||
|
definitionlist::
|
||
|
## code:: number @ number :: || make a link::Classes/Point:: of two numbers
|
||
|
code::
|
||
|
x @ y
|
||
|
// returns:
|
||
|
Point(x, y)
|
||
|
::
|
||
|
## code:: point @ point :: || make a link::Classes/Rect:: of two link::Classes/Point::s
|
||
|
code::
|
||
|
Point(left, top) @ Point(right, bottom)
|
||
|
// returns:
|
||
|
Rect(left, top, right-left, bottom-top)
|
||
|
::
|
||
|
## code:: ugen @ ugen :: || create a Point with two link::Classes/UGen::s
|
||
|
## code:: rect & rect :: || intersection of two rectangles
|
||
|
## code:: rect | rect :: || union of two rectangles (returns a Rect whose boundaries exactly encompass both Rects)
|
||
|
::
|
||
|
|
||
|
section:: IOStream operators
|
||
|
definitionlist::
|
||
|
## code:: 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.
|
||
|
code::
|
||
|
Post << "Here is a random number: " << 20.rand << ".\n";
|
||
|
Here is a random number: 13.
|
||
|
::
|
||
|
|
||
|
## code:: stream <<* collection :: || add each item of the collection to the stream.
|
||
|
code::
|
||
|
Post << [0, 1, 2, 3]
|
||
|
[ 0, 1, 2, 3 ]
|
||
|
|
||
|
Post <<* [0, 1, 2, 3]
|
||
|
0, 1, 2, 3
|
||
|
::
|
||
|
|
||
|
## code:: stream <<< object :: || add the object's compile string to the stream.
|
||
|
code::
|
||
|
Post <<< "a string"
|
||
|
"a string"
|
||
|
::
|
||
|
## code:: stream <<<* collection :: || add each item's compile string to the stream.
|
||
|
::
|
||
|
|
||
|
section:: Conditional execution operators
|
||
|
definitionlist::
|
||
|
## code:: object ? object :: || nil check (no .value)
|
||
|
## code:: 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.
|
||
|
code::
|
||
|
a = [nil, 5];
|
||
|
|
||
|
10.do({ (a.choose ? 20.rand).postln });
|
||
|
10.do({ (a.choose ?? { 20.rand }).postln });
|
||
|
::
|
||
|
code:: ?? { } :: is generally recommended. code::?:: always evaluates the second expression, even if its value will not be used.
|
||
|
code:: ?? :: 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 Slider not be created if the object was already passed in.
|
||
|
code::
|
||
|
f = { |slider, parent|
|
||
|
slider = slider ?? { Slider.new(parent, Rect(0, 0, 100, 20)) };
|
||
|
slider.value_(0);
|
||
|
};
|
||
|
::
|
||
|
If the first line inside the function instead read code::
|
||
|
slider = slider ? Slider.new(parent, Rect(0, 0, 100, 20));
|
||
|
::
|
||
|
, a new slider would be created even if it is not needed, or used.
|
||
|
|
||
|
## code:: object !? function :: || execute function if object is not nil.
|
||
|
code::
|
||
|
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.
|
||
|
code::
|
||
|
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
|
||
|
::
|
||
|
::
|
||
|
|
||
|
section:: Miscellaneous operators
|
||
|
definitionlist::
|
||
|
## code:: object ! number :: || same as code:: object.dup(number) ::
|
||
|
code::
|
||
|
15 ! 5
|
||
|
[ 15, 15, 15, 15, 15 ]
|
||
|
::
|
||
|
If the object is a function, it behaves like Array.fill(number, function).
|
||
|
code::
|
||
|
{ 10.rand } ! 5
|
||
|
[ 8, 9, 3, 8, 0 ]
|
||
|
::
|
||
|
## code:: object -> object :: || creates an link::Classes/Association::, used in dictionaries.
|
||
|
## code:: expression <! expression :: || bypass value of second expression.
|
||
|
This operator evaluates both expressions, and returns the value of the first.
|
||
|
code::
|
||
|
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
|
||
|
::
|
||
|
|
||
|
## code:: function <> function :: || function composition operator.
|
||
|
This operator returns a new function, which evaluates the second function and passes the result to the first function.
|
||
|
code::
|
||
|
f = { |a| a * 5 } <> {|a| a + 2 };
|
||
|
f.(10);
|
||
|
60 // == (10+2) * 5
|
||
|
::
|
||
|
An array as argument is passed through the chain:
|
||
|
code::
|
||
|
f.([10, 75, 512]);
|
||
|
[ 60, 385, 2570 ] // == ([10, 75, 512]+2) * 5
|
||
|
::
|
||
|
::
|
||
|
|
||
|
section:: Symbolic notations to define literals/other objects
|
||
|
definitionlist::
|
||
|
## code:: $ :: || character prefix: code:: "ABC".at(0) == $A ::
|
||
|
## code:: '' :: or code:: \ :: || define a literal link::Classes/Symbol:: : code:: 'abc' === \abc ::
|
||
|
## code:: "" :: || define a literal link::Classes/String:: : code:: "SuperCollider is the best" ::
|
||
|
## code:: [item, item...] :: || define an link::Classes/Array:: containing given items
|
||
|
## code:: Set[item, item...] :: || define a link::Classes/Set:: -- any link::Classes/Collection:: class name can be used other than Set
|
||
|
## code:: #[item, item...] :: || define a literal link::Classes/Array::
|
||
|
## code:: (a:1, b:2) :: || define an link::Classes/Event:: (same as code:: Event[\a -> 1, \b -> 2] ::)
|
||
|
## code:: ` :: (backtick or backquote) || define a link::Classes/Ref:: : code:: `1 == Ref(1), `(a+1) == Ref(a+1) ::
|
||
|
## code:: \ :: || inside a string or symbol, escapes the next character
|
||
|
code::
|
||
|
"abc\"def\"ghi"
|
||
|
abc"def"ghi
|
||
|
|
||
|
'abc\'def\'ghi'
|
||
|
abc'def'ghi
|
||
|
::
|
||
|
definitionlist::
|
||
|
## code:: \t :: || tab character
|
||
|
## code:: \n :: || newline character
|
||
|
## code:: \l :: || linefeed character
|
||
|
## code:: \r :: || carriage return character
|
||
|
## code:: \\ :: || \ character
|
||
|
::
|
||
|
|
||
|
## code:: { } :: || define an open function
|
||
|
## code:: #{ } :: || define a closed function
|
||
|
## code:: (_ * 2) :: || define a function code:: { |a| a * 2 } :: (see link::Reference/Partial-Application::)
|
||
|
::
|
||
|
|
||
|
section:: Argument definition
|
||
|
definitionlist::
|
||
|
## code:: |a, b, c| :: || define function/method arguments
|
||
|
## code:: |a, b ... c| :: || define function/method arguments; arguments after a and b will be placed into c as an array
|
||
|
## code:: #a, b, c = myArray ::|| assign consecutive elements of myArray to multiple variables
|
||
|
## code:: #a, b ... c = myArray :: || assign first two elements to a and b; the rest as an array into c
|
||
|
::
|
||
|
|
||
|
section:: Where f is a function
|
||
|
definitionlist::
|
||
|
## code:: f.( ) :: || evaluate the function with the arguments in parentheses
|
||
|
## code:: f.(*argList) :: || evaluate the function with the arguments in an array
|
||
|
## code:: f.(anArgName: value) :: || keyword addressing of function or method arguments
|
||
|
code::
|
||
|
f = { |a, b| a * b };
|
||
|
f.(2, 4);
|
||
|
f.(*[2, 4]);
|
||
|
f.(a: 2, b: 4);
|
||
|
::
|
||
|
## code:: SomeClass.[index] :: || Equivalent to SomeClass.at(index) -- Instr.at is a good example
|
||
|
## code:: myObject.method(*array) :: || call the method with the arguments in an array
|
||
|
## code:: obj1 method: obj2 :: || same as code::obj1.method(obj2):: or code::method(obj1, obj2)::.
|
||
|
This works only with single-argument methods like binary operators.
|
||
|
::
|
||
|
|
||
|
section:: Class and instance variable access
|
||
|
|
||
|
Inside a class definition (see link::Guides/WritingClasses:: ):
|
||
|
code::
|
||
|
{
|
||
|
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
|
||
|
|
||
|
// methods go here ...
|
||
|
}
|
||
|
::
|
||
|
These notations do not apply to variables defined within methods.
|
||
|
|
||
|
definitionlist::
|
||
|
## code:: ^someExpression :: || Inside a method definition: return the expression's value to the caller
|
||
|
## code:: instVar_ { } :: || define a setter for an instance variable
|
||
|
## code:: myObject.instVar = x; :: || invoke the setter: code:: (myObject.instVar_(x); x) ::
|
||
|
::
|
||
|
|
||
|
section:: Array series and indexing
|
||
|
definitionlist::
|
||
|
## code:: (a..b) :: || produces an array consisting of consecutive integers from a to b
|
||
|
## code:: (a, b..c) :: || e.g.: (1, 3..9) produces [1, 3, 5, 7, 9]
|
||
|
## code:: (..b) :: || produces an array 0 through b
|
||
|
## code:: (a..) :: || not legal (no endpoint given)
|
||
|
|
||
|
## code:: a[i..j] :: || same as code:: a.copySeries(i, j) :: (see link::Classes/ArrayedCollection#-copySeries::)
|
||
|
## code:: a[i, j..k] :: || e.g.: code:: a[1, 3..9] :: retrieves array elements 1, 3, 5, 7, 9
|
||
|
## code:: a[..j] :: || same as code:: a.copySeries(0, j) ::
|
||
|
## code:: a[j..] :: || same as code:: a.copySeries(i, a.size-1) :: (this is OK--Array is finite)
|
||
|
|
||
|
## code:: ~ :: || access an environment variable
|
||
|
## code:: ~abc :: || compiles to code:: \abc.envirGet ::
|
||
|
## code:: ~abc = value :: || compiles to code:: \abc.envirPut(value) ::
|
||
|
::
|
||
|
|
||
|
section:: Adverbs to math operators
|
||
|
(see link::Reference/Adverbs:: )
|
||
|
|
||
|
e.g.:
|
||
|
code::
|
||
|
[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 ] ]
|
||
|
::
|
||
|
definitionlist::
|
||
|
## code:: .s :: || output length is the shorter of the two arrays
|
||
|
## code:: .f :: || use folded indexing instead of wrapped indexing
|
||
|
## code:: .t :: || table-style
|
||
|
## code:: .x :: || cross (like table, except that the results of each operation are concatenated, not added as another dimension)
|
||
|
## code:: .0 :: || operator depth (see link::Guides/J-concepts-in-SC:: )
|
||
|
## code:: .1 :: || etc.
|
||
|
::
|
||
|
|