Verse Wiki — the Verse handbook for Blueprint authors
Bonus · EXTRA

Are Functions First-Class Citizens? Passing Functions in Verse

"Can I pass a function as an argument?" — a classic question from the Epic developer forums. The official docs barely touch it, but the answer is yes, and the syntax is surprisingly plain. This page follows that thread, drives "functions are values" all the way home, then draws the real-world boundary as it stands in today's UEFN.

1. The Classic Forum Question

The asker's confusion is highly representative: the docs show nowhere how a "function type" should be written — so can Verse functions be passed around like ordinary values or not? Delightfully, the top answer came from the asker himself: yes, you can — declare that input parameter in the shape of a function signature, spelling out what it eats and what it spits. His proof-of-concept was called EatTheFunction — feeding one function whole to another. Here it is, tidied up to this site's naming conventions:

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

Double(N:int):int = N * 2
AddTen(N:int):int = N + 10

# A parameter in signature shape can swallow any matching function
EatTheFunction(IntToInt(X:int):int, Num:int):int =
    IntToInt(Num)

first_class_device := class(creative_device):

    OnBegin<override>()<suspends>:void =
        A := EatTheFunction(Double, 21)    # 42
        B := EatTheFunction(AddTen, 32)    # 42
        Print("A={A} B={B}")

Blueprint translation: Double and AddTen are two ordinary functions. EatTheFunction's first input IntToInt(X:int):int is a "function socket" — any function that eats one int and spits one int plugs right in; inside the body, IntToInt(Num) takes whatever got plugged in and runs it once. In OnBegin (Event BeginPlay), Double and AddTen each get plugged in, so the same flow runs two different algorithms — both landing on 42.

The parameter IntToInt(X:int):int looks exactly like a function's signature — because it is one: any named function that "eats one int, spits one int" fits the slot. Inside the body, use it like an ordinary function. When passing it in, write Double without parentheses: parentheses mean casting on the spot; without them, what gets handed over is the function itself — and it's passed by reference (Double in person, not a copy).

2. Why It Works: Everything Computed Is a Value

The asker's self-answer, widely endorsed by the community: every piece of Verse code computes down to a value, functions included — so of course one can be handed off as an argument. That's not a coincidence — it's pedigree. Epic positions Verse as a functional logic language, so functions are born values. The deeper meaning of that = from Lesson 19 fully unfolds here: Double(N:int):int = N * 2 and MaxHealth:int = 100 are really the same kind of statement — both bind a name to a thing; the former's thing merely happens to "be runnable".

This buys you a very practical architectural feel: pulling the "how to compute" out of the "what to compute". EatTheFunction above is the minimal demo — same flow, swap the "skill book", get a different behavior. Damage formulas, loot weights, sort rules — all of them can become swappable function sockets while the main flow stays untouched, line for line.

3. The Real-World Boundary: No Lambdas, No Closures

Capabilities covered — now the boundary, so muscle memory from other tools doesn't walk you into a wall. First, as of the current UEFN release, Verse can't whip up a nameless little function on the spot (other languages call this a lambda literal): you can't inline a quick "comes in, ×2, goes out" mini function at the call site; to pass one, you must first define a function with a proper name, or use some object's method. Second, a function can't bundle up the surrounding variables and take them along (the term is closure capture): it can't pocket the temporary variables from wherever it was defined. To make a callback (like the logic you hang on with Bind Event in Blueprint) carry data with it — say a button index or a reward multiplier — the standard answer is storing the data in a class's fields and writing the callback as that class's method: the community's Handler class pattern (this lesson's other extra is devoted to it).

So the honest answer to "are functions first-class citizens?" is: citizenship granted, passport in order — they just can't travel incognito yet. The language's functional genes are right there; the current implementation chose a conservative subset — and for writing game logic, the two weapons of named functions plus Handler classes cover the vast majority of scenarios.

You want the function Run to accept any "int in, int out" function as a parameter. How should the parameter be declared?

In the current UEFN release, which of these can NOT be done?

Sources & Further Reading

Compiled from the Epic developer forums: