Verse Wiki — the Verse handbook for Blueprint authors
Deep Dive · EXTRA

Pure Nodes and Verse's Effect Specifiers

The main lesson said "nodes become function calls", but left one thing out: Blueprint nodes come in two shapes, with white execution pins and without. That distinction did not vanish in Verse — it moved somewhere much stricter: the function signature.

1. Look at the Pure Node Properly First

Some Blueprint nodes cannot take a white wire: Add, Get, Make Vector, Greater Than, Get Player Count. They have data pins only and no execution pins. These are Pure nodes, drawn as small green rounded boxes. They have three traits:

The load-bearing word in the third trait is convention. Tick the Pure option on a Blueprint function and the engine does not verify whether you quietly Set a variable inside the body. You ticked Pure, so it looks like a Pure node — that's the whole mechanism. The C++-side BlueprintPure marker works the same way: it's a promise written by the node's author, not a contract that gets checked. So in Blueprints, the accuracy of "is this node pure" depends on how disciplined its author was.

2. Verse Writes It Into the Function Signature

Verse's equivalent mechanism is the effect specifier, written in angle brackets after the function name and before the return type. You have been looking at one all along — the <suspends> at the end of the OnBegin<override>()<suspends>:void that shows up in every lesson.

score_device.verse
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }

score_device := class(creative_device):

    var Score:int = 100

    # Pure computation: takes arguments, returns a result, touches no mutable state
    Doubled(X:int)<computes>:int = X * 2

    # Might fail: passes if you can afford it, "fails" if you can't
    Afford(Price:int)<decides><transacts>:void =
        Score >= Price

    # No specifier = <transacts>: reads and writes, like a normal node on the white wire
    AddScore(N:int):void =
        set Score += N

    OnBegin<override>()<suspends>:void =
        Print("{Doubled(21)}")
        if (Afford(30)):
            AddScore(-30)
            Print("Bought it, {Score} left")

Three functions, three identities. Doubled is a Pure node through and through; AddScore is an ordinary node on the white wire (it sets a variable); Afford is a third thing Blueprints don't have — a function that "might not go through", which must be called somewhere failure is allowed, such as inside an if.

3. The Five You'll Hit First

There are more than five specifiers, but these five cover 95% of what you meet while migrating. What follows is "roughly what each governs"; defer to the official docs for exact semantics:

Specifier Roughly what it governs Blueprint analogy
<computes> Pure computation: the same input always yields the same output; neither reads nor writes mutable state The purest kind of Pure node (Add, Max and friends)
<converges> The "smallest" effect set: guaranteed to yield a value in finite time, never diverging No counterpart — Blueprints don't care whether your function can hang forever
<transacts> The default tier: may read, write and allocate; those actions sit in a transaction and can be rolled back together on failure An ordinary (Impure) node on the white wire
<decides> This function can fail; calling it is an expression that "might not go through", and it must be written somewhere failure is allowed Adding a bool output pin and wiring a Branch to check it by hand
<suspends> This function can pause, hand control to other concurrent work, and take several simulation updates to finish Latent nodes (Delay, Timeline — the ones with a clock icon in the corner)

One combination rule is worth memorizing: specifiers split into exclusive and additive. <converges> / <computes> / <transacts> are exclusive — a function picks at most one. <decides> / <suspends> / <reads> / <writes> / <allocates> are additive and can be written alongside an exclusive one, as in the <decides><transacts> above. There is one hard restriction: <decides> and <suspends> cannot be used together — "can be rolled back" and "can wait across frames" don't mix.

And if you write nothing at all? Per the official docs, a function with no specifier defaults to <transacts> — the equivalent of Blueprints handing you an Impure node by default: it reads, it writes, and it queues up on the white wire like everyone else. What you have to actively apply for is anything purer than the default (<computes>) or anything more special (<decides>, <suspends>).

One misconception to clear up while we're here: <computes> does not mean the result gets cached. As section 5 of the main lesson covered, Verse computes it however many times you wrote it. A specifier describes what the function is allowed to do, not how the engine will optimize it. If a value is used twice, you still have to name it.

4. The Big Difference: This Is a Contract, Not a Comment

The value of specifiers isn't in typing a few extra words — it's that the compiler checks them for you. Three concrete consequences:

Put another way: Blueprints draw "what this node does" into the node's appearance and rely on discipline and your eyes; Verse writes it into the signature and relies on the compiler. Open an unfamiliar .verse file and you don't have to read the body — one line of signature tells you whether that function changes state, whether it can fail, and whether it can stall for a few frames. In Blueprints, that information either requires opening the function graph and reading through it, or is unavailable entirely. Documentation became a contract.

There's a cost, naturally: another vocabulary to learn, and early on you'll be stopped by a pile of "this effect isn't allowed here" errors. The good news is that nearly all of those errors point at a real design question — they're asking what you actually want this function to do, and Blueprints never made you answer that.

5. Quick Quiz

A Blueprint Pure node (no execution pins, recomputed per wire, computes without modifying) is closest to which Verse specifier?

Sources

Compiled from Epic's official documentation and the official language book: Verse Glossary (official docs) ↗ · Specifiers and Attributes in Verse (official docs) ↗ · Book of Verse — Effects (official language book) ↗. For the full list of specifiers and their exact semantics, defer to the official documentation.