← Back to articles

Arguments and Symbols

Path: Computer Tech/Development/Programming Languages/PureData/Arguments and Symbols.mdUpdated: 2/3/2026

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

VariableContextWhen SetCan Change?Use Case
$0Object/MessagePatch loadNoUnique identifiers in abstractions
$1, $2...Object boxObject creationNoFixed parameters from creation arguments
$1, $2...Message boxMessage receivedYesDynamic value substitution
set $1Message to objectMessage sentYesUpdate 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