Decorators
Decorators transform a function, method, or class immediately after it is defined.
Syntax
Write each decorator as #[expr] on the lines immediately before the
declaration:
The decorator expression can be any callable expression, including a call that configures and returns a decorator:
Valid Positions
Decorators are valid in three places:
- Before a top-level
def - Before a top-level
class - Before a
definside a class body
They are not valid before let, field, or other statements.
pub goes after any decorators:
Semantics
Each decorator expression is evaluated in the surrounding scope before the function, method, or class value is bound to its name.
After the value is created, decorators are applied from bottom to top. Each decorator receives the current value and returns the replacement value to bind.
Conceptually, this binds work to outer(inner(<function value>)). The same
ordering applies to classes and methods.
Function Decorators
A decorator is usually a function that accepts the defined function and returns either the same function or a wrapped replacement.
let commands = []
def command name
do |func|
commands.push [name, func]
func
#[command "build"]
def build()
echo building
command runs when build is defined, not when build() is called.
Decorator factories are ordinary functions. command "build" evaluates first
and returns the actual decorator.
Class Decorators
Class decorators work the same way, but receive the class object:
let registry = {}
def register type
registry[str(type)] = type
type
#[register]
pub class Job
pub field name = ""
This is useful for registries, metadata attachment, or replacing the class with an adapted version.
Method Decorators
Method decorators receive the method function and return the value to install in the class under that name.
A decorator can convert a method into a computed field setter or getter by
replacing the method with a subtype of Getter or
Setter. The builtin getter and setter decorators
in the prelude do this in a straightforward manner.