Modifiers

A modifier wraps a function with extra behavior that runs before and after it, without changing the function's own code. Use modifiers for logging, timing, validation, or any cross-cutting concern you want to keep out of your core logic.

What are modifiers

A modifier is defined with #m name() ... #ef and contains two blocks:before:, which runs right before the wrapped function, andafter:, which runs right after it finishes.

💡 Tip:Modifiers don't take the function's arguments — they wrap execution, not data. Keep your logic for inputs inside the function itself.

Syntax

syntax.astra
#m test() before: write "start1" after: write "end1" #ef

And a regular function, defined the usual way:

syntax.astra
#f fun() write "original" #ef

Applying a modifier

Attach a modifier to a function call using square brackets:

apply.astra
fun() [test]

Output:

start1 original end1

The flow is straightforward — before runs, then the function body, then after:

before: write "start1"write "original"after: write "end1"

Multiple modifiers

You can stack more than one modifier on the same call, separated by commas:

multiple.astra
#m test() before: write "start1" after: write "end1" #ef #m test1() before: write "start2" after: write "end2" #ef #f fun() write "original" #ef fun() [test, test1]

Output:

start1 start2 original end2 end1

Execution order

With multiple modifiers, Astra wraps them in the order you list them — like layers around the function. before blocks run in the order listed (left to right), and after blocks run in the reverseorder (right to left). This is the same nesting pattern you'd see wrapping one function call inside another.

test beforetest1 beforeoriginaltest1 aftertest after
⚠️ Remember: The last modifier in the list runs its before last, but its after first — modifiers nest like brackets, not like a flat sequence.

Common use cases

Logging

logging.astra
#m logger() before: write "Starting..." after: write "Done!" #ef #f process(data) write "Processing: " + data #ef process("Astra") [logger] \\ Starting... -> Processing: Astra -> Done!

Timing

timing.astra
#m timer() before: write "Timer started" after: write "Timer stopped" #ef #f heavyTask() write "Doing heavy work..." #ef heavyTask() [timer]
✅ Next: Learn how to handle failures gracefully in Error Handling →