[BREAKING] Feat: quotation is now using ()

This commit is contained in:
2026-02-28 20:25:59 +01:00
parent ec98274dfe
commit 651ed1219d
24 changed files with 182 additions and 169 deletions

View File

@@ -75,7 +75,7 @@ Euclidean distribution via `euclid`:
Random timing via `gen`:
```forth
{ 0.0 1.0 rand } 4 gen at hat s . ;; 4 hats at random positions
( 0.0 1.0 rand ) 4 gen at hat s . ;; 4 hats at random positions
```
Geometric spacing via `geom..`:
@@ -89,10 +89,10 @@ Geometric spacing via `geom..`:
Wrap `at` expressions in quotations for conditional timing:
```forth
{ 0 0.25 0.5 0.75 at } 2 every ;; 16th-note hats every other bar
( 0 0.25 0.5 0.75 at ) 2 every ;; 16th-note hats every other bar
hat s .
{ 0 0.5 at } 0.5 chance ;; 50% chance of double-hit
( 0 0.5 at ) 0.5 chance ;; 50% chance of double-hit
kick s .
```

View File

@@ -40,15 +40,15 @@ That gives you 110, 220, 440, 880, 1760 (reversed), ready to feed into `freq`.
`gen` executes a quotation n times and collects all results. The quotation must push exactly one value per call:
```forth
{ 1 6 rand } 4 gen ;; 4 random values between 1 and 6
{ coin } 8 gen ;; 8 random 0s and 1s
( 1 6 rand ) 4 gen ;; 4 random values between 1 and 6
( coin ) 8 gen ;; 8 random 0s and 1s
```
Contrast with `times`, which executes for side effects and does not collect. `times` sets `@i` to the current index:
```forth
4 { @i } times ;; 0 1 2 3 (pushes @i each iteration)
4 { @i 60 + note sine s . } times ;; plays 4 notes, collects nothing
4 ( @i ) times ;; 0 1 2 3 (pushes @i each iteration)
4 ( @i 60 + note sine s . ) times ;; plays 4 notes, collects nothing
```
The distinction: `gen` is for building data. `times` is for doing things.
@@ -109,7 +109,7 @@ c4 e4 g4 b4 4 shuffle ;; random permutation each time
Useful for computing averages or accumulating values:
```forth
{ 1 6 rand } 4 gen 4 sum ;; sum of 4 dice rolls
( 1 6 rand ) 4 gen 4 sum ;; sum of 4 dice rolls
```
## Replication

View File

@@ -263,7 +263,7 @@ c4 mtof freq sine s .
A chord progression cycling every pattern iteration:
```forth
{ c3 maj7 } { f3 maj7 } { g3 dom7 } { c3 maj7 } 4 pcycle
( c3 maj7 ) ( f3 maj7 ) ( g3 dom7 ) ( c3 maj7 ) 4 pcycle
note sine s .
```
@@ -290,7 +290,7 @@ Chord voicings with random inversion:
```forth
e3 min9
{ } { 1 oct } 2 choose
( ) ( 1 oct ) 2 choose
note modal s .
```

View File

@@ -31,8 +31,8 @@ These are useful for parameters where perception is logarithmic, like frequency
The probability words take a quotation and execute it with some chance. `chance` takes a float from 0.0 to 1.0, `prob` takes a percentage from 0 to 100:
```forth
{ hat s . } 0.25 chance ;; 25% chance
{ hat s . } 75 prob ;; 75% chance
( hat s . ) 0.25 chance ;; 25% chance
( hat s . ) 75 prob ;; 75% chance
```
Named probability words save you from remembering numbers:
@@ -48,9 +48,9 @@ Named probability words save you from remembering numbers:
| `never` | 0% |
```forth
{ hat s . } often ;; 75%
{ snare s . } sometimes ;; 50%
{ clap s . } rarely ;; 25%
( hat s . ) often ;; 75%
( snare s . ) sometimes ;; 50%
( clap s . ) rarely ;; 25%
```
`always` and `never` are useful when you want to temporarily mute or unmute a voice without deleting code. Change `sometimes` to `never` to silence it, `always` to bring it back.
@@ -58,8 +58,8 @@ Named probability words save you from remembering numbers:
Use `?` and `!?` with `coin` for quick coin-flip decisions:
```forth
{ hat s . } coin ? ;; execute if coin is 1
{ rim s . } coin !? ;; execute if coin is 0
( hat s . ) coin ? ;; execute if coin is 1
( rim s . ) coin !? ;; execute if coin is 0
```
## Selection
@@ -74,7 +74,7 @@ kick snare hat 3 choose s . ;; random drum hit
When a chosen item is a quotation, it gets executed:
```forth
{ 0.1 decay } { 0.5 decay } { 0.9 decay } 3 choose
( 0.1 decay ) ( 0.5 decay ) ( 0.9 decay ) 3 choose
sine s .
```
@@ -115,7 +115,7 @@ The difference matters when patterns have different lengths. `cycle` counts per-
Quotations work here too:
```forth
{ c4 note } { e4 note } { g4 note } 3 cycle
( c4 note ) ( e4 note ) ( g4 note ) 3 cycle
sine s .
```
@@ -130,20 +130,20 @@ sine s .
`every` runs a quotation once every n pattern iterations:
```forth
{ crash s . } 4 every ;; crash cymbal every 4th iteration
( crash s . ) 4 every ;; crash cymbal every 4th iteration
```
`except` is the inverse -- it runs a quotation on all iterations *except* every nth:
```forth
{ 2 distort } 4 except ;; distort on all iterations except every 4th
( 2 distort ) 4 except ;; distort on all iterations except every 4th
```
`bjork` and `pbjork` use Bjorklund's algorithm to distribute k hits across n positions as evenly as possible. Classic Euclidean rhythms:
```forth
{ hat s . } 3 8 bjork ;; tresillo: x..x..x. (by step runs)
{ hat s . } 5 8 pbjork ;; cinquillo: x.xx.xx. (by pattern iterations)
( hat s . ) 3 8 bjork ;; tresillo: x..x..x. (by step runs)
( hat s . ) 5 8 pbjork ;; cinquillo: x.xx.xx. (by pattern iterations)
```
`bjork` counts by step runs (how many times this particular step has played). `pbjork` counts by pattern iterations. Some classic patterns:
@@ -172,7 +172,7 @@ The real power comes from mixing techniques. A hi-hat pattern with ghost notes:
```forth
hat s
{ 0.3 0.6 rand gain } { 0.8 gain } 2 cycle
( 0.3 0.6 rand gain ) ( 0.8 gain ) 2 cycle
.
```
@@ -181,18 +181,18 @@ Full volume on even runs, random quiet on odd runs.
A bass line that changes every 4 bars:
```forth
{ c2 note } { e2 note } { g2 note } { a2 note } 4 pcycle
{ 0.5 decay } often
( c2 note ) ( e2 note ) ( g2 note ) ( a2 note ) 4 pcycle
( 0.5 decay ) often
sine s .
```
Layered percussion with different densities:
```forth
{ kick s . } always
{ snare s . } 2 every
{ hat s . } 5 8 bjork
{ rim s . } rarely
( kick s . ) always
( snare s . ) 2 every
( hat s . ) 5 8 bjork
( rim s . ) rarely
```
A melodic step with weighted note selection and random timbre:

View File

@@ -53,7 +53,7 @@ Reset on some condition:
```forth
@n 1 + !n
{ 0 !n } @n 16 > ? ;; reset after 16
( 0 !n ) @n 16 > ? ;; reset after 16
```
## When Changes Take Effect