This PR adds support for default parameter values in function definitions, reducing boilerplate and improving API ergonomics:
// Define with defaults
lowpass(freq, q=0.707) = fi.resonlp(freq, q, 1);
// Call - omit defaulted parameters
process = lowpass(1000); // q = 0.707
process = lowpass(1000, 1.5); // q = 1.5Currently, Faust functions require all parameters at every call site, even when sensible defaults exist:
// Without defaults - must specify q every time
lowpass(freq, q) = fi.resonlp(freq, q, 1);
process = lowpass(1000, 0.707), lowpass(2000, 0.707), lowpass(500, 0.707);
// With defaults - cleaner code
lowpass(freq, q=0.707) = fi.resonlp(freq, q, 1);
process = lowpass(1000), lowpass(2000), lowpass(500);This could be especially valuable for library functions where most users want standard values but experts need tunability.
// Single default
gain(x, amount=1.0) = x * amount;
// Multiple defaults (must be rightmost parameters)
mix(a, b, ratio=0.5) = a * (1-ratio) + b * ratio;
env(attack=0.01, decay=0.1, sustain=0.7, release=0.3) = ...;
// Defaults can be expressions
SR = 48000;
nyquist(sr=SR/2) = sr;
// Defaults can reference earlier parameters
scale(x, factor, offset=factor*0.1) = x * factor + offset;Constraints:
- Parameters with defaults must come after parameters without defaults
- Default expressions are evaluated at definition time
- Parser: Extended function parameter syntax to accept
= expression - Boxes: Default values stored by position (nil for required params)
- Eval: Modified function application to fill missing arguments from defaults
Pass tests:
default-params-basic.dsp- single default parameterdefault-params-multiple.dsp- multiple defaults in one functiondefault-params-expression.dsp- defaults using expressions/constants
The large diff in generated files (faustparser.cpp, etc.) is from flex/bison regeneration. Actual source changes:
| File | Lines changed |
|---|---|
faustparser.y |
+97 |
global.hh |
+6 |
sourcereader.cpp |
+16/-9 |
Fully backward compatible - existing function definitions without defaults work unchanged.
Combines naturally with keyword arguments (separate PR):
filter(freq, q=0.707, gain=1.0) = ...;
// All these work:
process = filter(1000);
process = filter(1000, 1.5);
process = filter(1000, gain: 2.0); // skip q, override gain
process = filter(freq: 1000, gain: 2.0); // named + default- Branch:
feature/default-parameters - Base:
master-dev
@sletz thanks to you both for for taking the time to review!