Often, there is not a pattern that delivers exactly the desired result by itself. But, other operations can be applied to patterns, to manipulate one pattern's output and turn it into something else.
Some of these operations look like things you would do to an array, but there is a critical difference. Doing math on an array performs the operation on every array item all at once. By contrast, patterns are "lazy" -- they evaluate one value at the time, only when asked, and they only do as much as they need to do to deliver the next value. An operation on a pattern produces another pattern that remembers the work that is to be done. Making a stream out of the composite pattern creates the structure to perform the operation upon request.
For example, multiplying a pattern by a number produces a "binary operator pattern": Pbinop. Looking at the Pbinop's variables reveals everything that is needed to reconstruct the operation on demand.
In other words, the multiplication here produces not the result of a single multiplication, but a template for an infinite stream of multiplications to follow.
Not only can patterns generate numbers, but they also support all the standard math operators: unary (abs, reciprocal, etc.), binary (+, -, *, /, **, min, max, etc.) and n-ary (clip, wrap, fold, linlin, linexp, etc.) operators are all valid with patterns.
If a binary operation occurs on two patterns, every time a value is requested from the resulting stream, both of the component streams are asked for a value, and the operator applies to those results. If either stream ends, the binary operator stream also ends.
The binary operator adverb .x
is supported with patterns. (See Adverbs for Binary Operators.) This adverb is like a nested loop: in streamA +.x streamB
, the first value of streamA is added to every value of streamB in succession, then the second value of streamA is added to every streamB value, and so on. This is an easy way to transpose a pattern to different levels successively.
Some of the things you can do to arrays also work with patterns.
collect(func)
select(func)
reject(func)
clump(n)
.clump
on an array turns a flat array into a multilevel array. Similarly, .clump
on a pattern gets n values from the pattern at once and returns all of them as an array. n can be a number or a numeric pattern.flatten(levels)
drop(n)
differentiate
These are some other numeric calculations that don't exactly fall in the category of math operators.
Pavaroh(pattern, aroh, avaroh, stepsPerOctave)
PdegreeToKey(pattern, scale, stepsPerOctave)
'degree'
event key, but there might be cases where you would want to do some further math on the note numbers, and it might be necessary to make the conversion explicit.Pdiff(pattern)
differentiate
method discussed just above.Prorate(proportion, pattern)
pattern
according to proportion(s) given by the proportion
pattern. This is tricky to explain briefly; see the help file for some good examples.
In a Pbind, normally the patterns for the various keys calculate independently. But it's possible for one or more child patterns to depend on the result of another pattern inside the same Pbind. This is done with Pkey, described in Pattern Guide 06g: Data Sharing.
Previous: Pattern Guide 04: Words to Phrases
Next: Pattern Guide 060: Filter Patterns