Verse Programming Language Documentation

repository·main·Indexed 42 days ago

https://github.com/verselang/book

Documentation for Verse, a functional logic programming language developed by Epic Games for interactive experiences in Unreal Engine and Fortnite. Includes guides on syntax, semantics, concurrency, and the verse_api CLI tool for extracting runtime API documentation from fortniteMain checkouts.

Tokens
177.8K
Snippets
538
Records
743
Agent score
54%

What's inside Verse

  1. Overview of Verse primitive data types

    main

    Verse includes several primitive types for different data requirements:

    • Numeric types: int (integers), float (IEEE 64-bit floating-point), and rational (exact fractions).
    • Boolean: logic.
    • Text: char, char32, and string.
    • Special types: any (the supertype of all types) and void (discards its input).
  2. Overview of Verse container types

    main

    Verse provides five primary container types for managing collections of data:

    1. Optional (?t): Holds either a value of type t or nothing.
    2. Tuple: Groups a fixed number of values, which may have different types.
    3. Array ([]t): Holds any number of values of a single type, supporting indexed access.
    4. Map ([k]v): Associates keys of type k with values of type v.
    5. weak_map: A specialized map that does not keep its keys alive, used as the basis for persistent storage.
  3. Access the Verse Programming Language Documentation

    main

    The comprehensive documentation for the Verse programming language, covering syntax, semantics, core concepts (expressions, primitives), and advanced features (concurrency, effects, persistence), is hosted online at the official Verse book website.

    https://verselang.github.io/book/
  4. Reference the Verse Concept Index

    main
    The Concept Index serves as a central directory for all key language features, types, and control structures in Verse. Use this index to locate detailed documentation for specific topics such as the Type System, Effects, Control Flow, Concurrency, Live Variables, and Mutability.
  5. Overview of Verse Access Specifiers

    main

    Verse uses access specifiers to control the visibility and accessibility of definitions (modules, classes, interfaces, structs, enums, methods, and data members). Choosing the correct specifier is critical for API stability, especially when publishing code, as <public> members represent a permanent contract with consumers.

    SpecifierVisibilityUsage
    <public>Universally accessibleMembers intended for external use
    <internal>Only within the module (default)Module-private implementation
    <private>Only in immediate enclosing scopeLocal to class/struct
    <protected>Current class and subtypesInheritance hierarchies
    <scoped>Current scope and enclosing scopesSpecial use cases
    <epic_internal>Scopes with the /Verse.org, /UnrealEngine.com, and /Fortnite.com domainsOnly usable by Epic-authored code
  6. Use tasks for asynchronous execution

    main

    A task is an asynchronous, stateful future obtained via a spawn expression. It represents a context executing concurrently in a cooperatively multitasked environment.

    Key constraints and behaviors:

    • Instantiation: You cannot instantiate a task directly or derive from it (it is <abstract><final>). You can only obtain one via spawn.
    • Public API: The only public member is Await. Other lifecycle methods like Cancel() or phase predicates (e.g., Completed[]) are internal.
    • Awaiting vs. Ownership: Awaiting a task does not create a parent-child relationship. If you cancel the code that is Await-ing a task, the task itself will continue to run. This differs from structured concurrency blocks where cancelling a parent cancels all children.
    MyTask := spawn { SomeAsyncFunction() }
    # ... do other work ...
    MyTask.Await()
  7. Use let clauses in archetype expressions

    main

    Archetype expressions (used for constructing instances) can include let clauses to introduce local bindings. These bindings are useful for computing intermediate values used by multiple field initializers, helping to avoid repetition.

    Restrictions:

    • let permits only declarations.
    • You cannot use mutating assignment (e.g., set X += 3) inside an archetype body; initialize each field once with := and mutate via methods or blocks afterward.
    rect := class:
        Width:int
        Height:int
        Area:int
    
    Square := rect:
        let:
            S:int = 4    # Computed once, used by three initializers
        Width := S
        Height := S
        Area := S * S
  8. Comparison Operations and Chaining

    main

    Comparison operators (e.g., <, >, <=, >=, <>) return their left operand when the comparison succeeds.

    Comparison Chaining Verse supports a special syntax for range checking: A <= B <= C. This is not evaluated as (A <= B) <= C. Instead, it checks both A <= B and B <= C simultaneously, returning the leftmost operand (A) on success.

    # Returns the left operand on success
    Left := 0 < 10
    # Left = 0
    
    # Range check syntax
    Value := 50
    if (0 <= Value <= 100) then InRange()
    
    # Inequality check
    Different := logic{A <> B}
  9. Understand the Listenable interface

    main

    A listenable(type) is a parametric interface that combines awaitable(payload) and subscribable(payload). It allows an API to provide two ways to react to changes: waiting for an event (via Await) or registering a callback (via subscription).

    In practice, listenable is commonly used for public event fields. For example, an agent_group_interface might expose membership changes as listenable(tuple(agent, member_info)).

    Note: The event type itself does not implement listenable; listenable is implemented by internal classes that wrap events to provide this dual interface.

  10. Understand the relationship between `void`, `any`, and `false`

    main

    Verse uses a hierarchy of universal and bottom types:

    • any: A universal supertype that erases type information.
    • void: A universal supertype where all types are subtypes of void. It represents a 'discard' type.
    • false: The bottom type. It is an uninhabited type (contains no values) and is a subtype of all other types.
  11. Animate entities using KeyframedMovement

    main

    The KeyframedMovement module provides a self-contained way to move an entity along a predefined path using a keyframed_movement_component and keyframed_movement_delta objects.

    Key Concepts:

    • Relative Design: Keyframes are defined as deltas from the previous keyframe. Using SetKeyframes rebases the entire path onto the entity's current transform, making authored paths reusable from any starting position.
    • Namespacing: All components and functions are declared inside the module. You must either qualify them (e.g., KeyframedMovement.linear_easing_function{}) or use a using KeyframedMovement statement.
    • Easing: Each leg of the journey (keyframed_movement_delta) can be shaped by an easing_function to control velocity.
  12. Use the `<decides>` effect for validation and control flow

    main

    The <decides> effect belongs to the cardinality family. It allows a function to fail, turning failure into a control flow mechanism. Instead of checking conditions and then acting, you use the check itself to drive the program's path via the square bracket [] syntax.

    When a function marked <decides> fails, it produces no value. You can use if to branch based on success or not to check for failure.

    ValidateHealth(Health:float)<transacts><decides>:void =
        Health > 0.0      # Fails if health is zero or negative
        Health <= 100.0   # Fails if health exceeds maximum
    
    # The check itself is the branch
    if (ValidateHealth[50.0]):
        Print("Combat starts")
    
    not ValidateHealth[0.0]
    not ValidateHealth[150.0]