# Arguments and Symbols in PureData PureData uses dollar sign variables (`$0`, `$1`, `$2`, etc.) for different purposes depending on context. Understanding how these work with arguments, set messages, and symbols is fundamental to creating flexible and reusable patches. ## Dollar Sign Variables Overview PureData has two main contexts for dollar variables: 1. **Object arguments** - `$1`, `$2`, `$3`, etc. in object boxes 2. **Patch-local identifiers** - `$0` for unique identification within abstractions ## `$0` - Patch-Local Unique Identifier **Purpose:** `$0` provides a unique number for each instance of an abstraction or subpatch. This prevents naming collisions when multiple instances exist. **Key characteristics:** - Automatically assigned by PureData when patch loads - Different for each abstraction instance - Same throughout a single patch instance - Commonly used for send/receive pairs, arrays, and tables **Example use case:** ``` [r $0-frequency] ← Receives from unique channel [osc~] [s $0-output] ← Sends to unique channel ``` When you create multiple instances of this abstraction, each gets its own `$0` value (e.g., 1001, 1002, 1003), ensuring `1001-frequency` doesn't conflict with `1002-frequency`. ## `$1`, `$2`, `$3` - Creation Arguments **Purpose:** These represent arguments passed when creating an object. They are **replaced at creation time** and become fixed values. **Key characteristics:** - Set when object is created - Cannot be changed dynamically - Used in **object boxes** only (rectangular boxes) - Evaluated left-to-right from the object's arguments **Example in object box:** ``` [osc~ $1] ← OBJECT BOX: If created as [osc~ 440], $1 becomes 440 ``` If you type `[osc~ 440]` in a patch, PureData creates an oscillator at 440 Hz. The `$1` is replaced with `440` at creation. **Another example - receive object:** ``` [r $1-frequency] ← OBJECT BOX: If created as [r 1001-frequency], $1 is replaced with 1001 at creation ``` **Important:** You create these as **object boxes**, not message boxes. In PureData: - **Object box** = rectangular with sharp corners → `[r $1-ff]` - **Message box** = rectangular with rounded top → `(set $1(` ← Different behavior! ### Combining `$0` and Creation Arguments A common pattern combines both: ``` [table $0-buffer $1] ``` If this is in an abstraction called `[mysampler 1024]`: - `$0` might be `1001` (unique instance ID) - `$1` is `1024` (creation argument) - Result: `[table 1001-buffer 1024]` ## Arguments vs Set Messages ### Using Arguments (Static) ``` [osc~ 440] ← Frequency fixed at creation ``` ### Using Inlet + Set Message (Dynamic) ``` [set $1( ← Message box that will replace object's argument | [osc~ 440] ← Can be updated dynamically ``` **The `set` message** tells an object to replace its internal parameter without triggering output. This is different from sending a value directly. **Example with `[float]` (f):** ``` [100( | [set $1( | [f] ← Sets to 100 but doesn't output | [bang( ← Triggers output of 100 ``` ## Symbols and Symbol Arguments **Symbols** are text identifiers in PureData. When using `$1`, `$2` with symbols, they can represent text rather than numbers. **Example:** ``` [symbol $1] ← If created as [symbol myname], outputs "myname" ``` ### Symbol Substitution in Messages In **message boxes** (rounded top), `$1` refers to **inlet values** received at runtime, not creation arguments: ``` [440( ← Number box | [set $1( ← MESSAGE BOX: $1 gets value from inlet (440) when triggered | [osc~] ``` **Key difference:** - **Object box** `[r $1-ff]` → `$1` replaced at creation time (static) - **Message box** `(set $1(` → `$1` replaced when message is triggered (dynamic) This is why you use **object boxes** for receive channels in abstractions - you want the channel name to be determined at creation, not at runtime. ## Practical Workflow Examples ### Example 1: Abstraction with Configurable Parameters **File: `myosc.pd`** ``` [inlet] | [* $1] ← $1 = frequency multiplier (creation argument) | [osc~] | [*~ $2] ← $2 = amplitude (creation argument) | [outlet~] ``` **Usage in parent patch:** ``` [440( | [myosc 2 0.5] ← 2x frequency multiplier, 0.5 amplitude | [dac~] ``` ### Example 2: Using `$0` for Local Send/Receive **File: `envelope.pd`** ``` [inlet] | [s $0-trigger] [r $0-trigger] | [line~] | [outlet~] ``` Each instance has isolated communication via unique `$0` values. ### Example 3: Parent Patch Broadcasting to Multiple Abstraction Instances **Problem:** You want to send a fundamental frequency to multiple instances of a `partial` abstraction without collisions between different parent patches (e.g., square wave vs triangle wave patches). **Solution:** Use `$0` in the **parent patch** to create a unique send channel, and have abstractions receive from it using `$0` passed as a creation argument. **Parent patch: `square-wave.pd`** ``` [440( ← Fundamental frequency input | [s $0-ff] ← Send to THIS patch's unique ff channel [partial $0 1] ← 1st harmonic (fundamental) | [partial $0 3] ← 3rd harmonic | [partial $0 5] ← 5th harmonic (square waves use odd harmonics) | [partial $0 7] ← 7th harmonic | [+~] | [dac~] ``` **Abstraction: `partial.pd`** ``` [r $1-ff] ← OBJECT BOX: $1 replaced at creation with parent's $0 | [* $2] ← OBJECT BOX: $2 is the harmonic number (1, 3, 5, 7...) | [osc~] | [outlet~] ``` **Important:** `[r $1-ff]` is an **object box** (not a message box). When you create `[partial 1001 3]` in the parent: - `$1` becomes `1001` → object becomes `[r 1001-ff]` - `$2` becomes `3` → object becomes `[* 3]` - These values are **fixed at creation time** **How it works:** 1. Parent patch `square-wave.pd` has its own `$0` value (e.g., `1001`) 2. It sends fundamental frequency to `[s 1001-ff]` 3. Each `[partial 1001 N]` instance receives from `[r 1001-ff]` and multiplies by its harmonic number 4. A separate `triangle-wave.pd` would have `$0` = `1002`, creating `[s 1002-ff]` with no collision **Critical Note: Why Pass `$0` as an Argument?** Each abstraction instance has its **own unique `$0` value**, completely separate from the parent's `$0`: - Parent `square-wave.pd`: `$0` = `1001` - First `[partial]` instance: `$0` = `1005` - Second `[partial]` instance: `$0` = `1006` - Third `[partial]` instance: `$0` = `1007` If you tried to use `[r $0-ff]` directly in `partial.pd`, each instance would listen to a different channel (`1005-ff`, `1006-ff`, `1007-ff`), and the parent couldn't broadcast to all of them. **By passing the parent's `$0` as `$1`, all instances subscribe to the same channel.** **Alternative: Global Send/Receive (No Isolation)** If you don't need isolation between different parent patches: **Parent: `square-wave.pd`** ``` [440( | [s ff] ← Global send (no $0) [partial 1] ← Only pass harmonic number [partial 3] ``` **Abstraction: `partial.pd`** ``` [r ff] ← Global receive | [* $1] ← Harmonic multiplier | [osc~] ``` **Trade-off:** Simpler (no need to pass `$0`), but you can't run multiple waveform patches simultaneously without interference. ### Example 4: Dynamic Parameter Changes with Set **Changing oscillator frequency without clicks:** ``` [metro 1000] | [random 1000] | [+ 200] | [set $1( ← Prepare new frequency | [bang( ← Trigger change at zero-crossing | [osc~] ``` The `set` message updates the frequency parameter, and the bang triggers the change smoothly. ## Common Pitfalls ❌ **Trying to change creation arguments dynamically:** ``` [440( | [osc~ $1] ← This does NOT work - $1 is fixed at creation ``` ✅ **Instead, send values to the inlet:** ``` [440( | [osc~] ← Send directly to inlet for dynamic control ``` ❌ **Forgetting `$0` in abstractions:** ``` [r frequency] ← Conflicts if multiple instances exist ``` ✅ **Use `$0` for unique naming:** ``` [r $0-frequency] ← Each instance has unique channel ``` ❌ **Hardcoding send/receive names across parent and abstractions:** ``` Parent: [s ff] Abstraction: [r ff] ← All parent patches share same channel! ``` ✅ **Pass parent's `$0` to abstractions:** ``` Parent: [s $0-ff] and [myabstraction $0] Abstraction: [r $1-ff] ← Uses parent's unique namespace ``` ## Summary Table | Variable | Context | When Set | Can Change? | Use Case | |----------|---------|----------|-------------|----------| | `$0` | Object/Message | Patch load | No | Unique identifiers in abstractions | | `$1`, `$2`... | Object box | Object creation | No | Fixed parameters from creation arguments | | `$1`, `$2`... | Message box | Message received | Yes | Dynamic value substitution | | `set $1` | Message to object | Message sent | Yes | Update object parameter without output | ## Related Topics - [[PureData Abstractions]] - Creating reusable patches - [[Send and Receive in PureData]] - Global vs local communication - [[Message Boxes vs Object Boxes]] - Understanding PureData's dual syntax ## References - PureData Documentation: [Arguments in Abstractions](http://puredata.info/) - Miller Puckette's "Theory and Techniques of Electronic Music"