rsc3/doc-schelp/HelpSource/Overviews/SymbolicNotations.schelp

387 lines
13 KiB
Text
Raw Permalink Normal View History

2022-08-24 13:53:18 +00:00
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.
::