A SynthDef is a reusable named synth recipe; a Synth is a running instance of it
SuperCollider separates a synth’s definition from its instantiation, a relationship like classes and instances. SynthDef(\name, {…UGen graph…}).add compiles the UGen network and registers it on the server once (it persists until SC quits; .store also writes it to disk); Synth(\name) then stamps out instances cheaply and repeatedly, and Synth(\name, [\freq, 660, \amp, 0.3]) overrides declared arguments at creation. Arguments with defaults become real-time controllable parameters, so x.set(\freq, 880) retunes a running instance. A named SynthDef requires explicit routing with Out.ar(bus, signal) — a common mistake is omitting Out and hearing silence — unlike the implicit output of {}.play, which internally creates an anonymous SynthDef (the temp_101 names seen in the Node Tree). A key subtlety: the graph function runs only once, at definition time, so a plain language-side expression inside it (e.g. rrand(200,800)) is fixed for every instance; to vary a value per instance use a server-side UGen like Rand. Named SynthDefs are what let Pbind play them via \instrument.
Examples
SynthDef(\sine, { arg freq=440, amp=0.1;
Out.ar(0, SinOsc.ar(freq, 0, amp))
}).add;
Synth(\sine); // default args
x = Synth(\sine, [\freq, 880]); // override at creation
x.set(\freq, 660); // retune live
x.free;
Assessment
Write a SynthDef for a saw with frequency and amplitude arguments, add it, instantiate three copies at different pitches without re-evaluating the block, then change one copy’s amplitude at runtime with .set(). Explain why SynthDef("x", { rrand(200,800).postln }).add followed by ten Synth("x") calls prints the same number every time, and how to get a different frequency per instance. State what happens if you call Synth before the SynthDef is added.