Gin's @gin.register limits side-effects by only injecting defaults when a function is used as an argument
DDSP uses the gin library for dependency injection of hyperparameters. Two decorators exist: @gin.configurable makes a function globally configurable — wherever it is called, gin sets its defaults, which can cause unintended side effects. @gin.register only injects defaults when the function is itself passed as an argument to another function. DDSP’s convention is to wrap most functions with @gin.register so hyperparameters can be specified without side effects, reserving @gin.configurable for high-level entry points like ProcessorGroup, Model, train(), and evaluate(). This pattern allows a single .gin file to specify an entire experiment.
Examples
# @gin.register: safe, only applies when used as an arg
@gin.register
def exp_sigmoid(x, exponent=10.0, max_value=2.0, threshold=1e-7): ...
# @gin.configurable: applies globally — use sparingly
@gin.configurable
def oscillator_bank(frequency_envelopes, ..., use_angular_cumsum=False): ...
Assessment
Explain when @gin.register is safer than @gin.configurable. If two independent modules both use exp_sigmoid and you make it configurable, what unintended behavior could occur?