Verbs

A mutating verb takes its outputs first, as a NamedTuple it destructures — f!((; Y), X; kws...) — and describes them with outputs. Its Allocating form is the same verb with the first argument answering where results live instead of which arrays: a Space the outputs materialize from, before any frame opens.

Pol.AllocatingType
Allocating(f!)

The allocating form of a mutating verb: a callable that owns the outputs/scratch ritual so call sites don't repeat it.

const decode_attention = Allocating(decode_attention!)
o = decode_attention(space, q, K, V; lengths)

The first argument answers where results live — the mutating verb takes its output buffers there, the allocating form takes a Space to materialize them from. Calling it allocates outputs from spacebefore any frame opens, so on an Arena they sit below the frame's mark and survive its retract — then runs f! and returns the outputs NamedTuple. A verb marked @takes_space runs inside a scratchspace block and receives the frame as its space keyword: its defaulted scratch is carved there and reclaimed at return.

space may itself be a Frame — frames are spaces and nest — in which case the outputs take the caller's frame lifetime.

The output_override keyword merges caller-owned arrays over the outputs spec before materialization, so an overridden entry is never allocated — pass the verb's own state array to run partially in place: f(space, args..., S; output_override = (; S′ = S)).

source
Pol.takes_spaceFunction
takes_space(f!) -> Bool

Whether the mutating verb f! accepts a space keyword — the space its defaulted scratch materializes from. false generically; declare with @takes_space. Allocating branches on it: a verb that takes no space is called bare, with no frame opened on its behalf.

source
Pol.@takes_spaceMacro
Pol.@takes_space f!

Declare that the mutating verb f! accepts a space keyword (see takes_space). One line next to the verb's scratch method:

Pol.@takes_space decode_attention!
source