# > | = ~ @ ?

Futuruna Basics

Core language syntax: literals, types, operators, control flow, and closures.

New to the language? The guided tutorial builds a small rule-driven program, runs a concrete scenario, attaches typed metadata, and audits an actual same-rule contradiction.

Literals

Numbers

42          -- Int (i64)
3.14        -- Float (f64)
-7          -- negative Int

Booleans

True        -- capitalized
False

Strings

"hello"                     -- basic string
"line\nnewline"             -- escape sequences: \n \t \\ \"

"""
multi-line string
preserves newlines
"""

"""Result: {{x + 5}}"""    -- interpolation with {{ expr }}

Interpolation desugars to "Result: " + show(x + 5).

Characters

'a'         -- single character (Char type, compiles to Rust char)

Lists

[1, 2, 3]               -- list literal
[]                       -- empty list

Unit

()                       -- unit value and unit type

Layout and Multiline Syntax

A newline normally ends a statement. It is a continuation instead when the grammar makes continuation unambiguous:

  • inside parentheses (...) or brackets [...];
  • after an incomplete token such as =, ->, ,, or an operator; or
  • before a continuation token such as |>, ., under, or else.

This lets compact and multiline forms mean the same thing:

= compact = calculate(case, [1, 2, 3]) |> cap(100)

= multiline =
    calculate(
        case,
        [
            1,
            2,
            3,
        ],
    )
    |> cap(100)

Delimited sequences accept a trailing comma. This applies consistently to function and rule parameters, calls, constructors, type fields and arguments, patterns, lists, tuples, closures, proof arguments, effect handlers, and grouped @ use imports. The formatter keeps one item per line when a sequence is already multiline.

Block braces {...} contain statements, so their newlines remain statement boundaries. Explicit list-shaped brace syntax, such as grouped @ use {...} imports, handles its own comma-separated items. Continue a block expression by leaving an incomplete token at the end of the line:

> total(base: Int, adjustment: Int) -> Int {
    base +
    adjustment
}

For algebraic data types, put | after a variant when another variant follows. That makes the continuation explicit without confusing the next variant with a top-level rule:

# Shape =
    Circle(radius: Float) |
    Rectangle(
        width: Float,
        height: Float,
    )

Do not rely on continuation inference for a line-leading +, -, or ||. Put these operators at the end of the preceding line, or wrap the whole expression in parentheses, to make the intended continuation explicit.

Types

Primitives

TypeRust equivalentExample
Inti6442
Floatf643.14
StringString"hello"
BoolboolTrue
Charchar'a'
()()()

Composite

TypeRust equivalentExample
List(a)Vec<A>[1, 2, 3]
Option(a)Option<A>Some(42), None
Result(a, e)Result<A, E>Ok(42), Err("fail")
Pair(a, b)Pair<A, B> (struct with fst, snd fields)Pair(1, "x")

Tuple literals may span lines and may end in a trailing comma:

= sources = (
    primary_source,
    amendment_source,
)

Pair construction and field access:

= p = Pair(1, "hello")
@ print(show(p.fst))          -- 1
@ print(show(p.snd))          -- "hello"

Function types

Int -> Bool              -- function from Int to Bool
(Int, Int) -> String     -- two-argument function
a -> b                   -- generic function type

Generic type variables

Lowercase single letters are type variables: a, b, c, etc. They become uppercased Rust generics (A, B, C). Uppercase names like T pass through unchanged.

Operators

Arithmetic (precedence low to high)

OpMeaning
+, -addition, subtraction
*, /, %multiplication, division, modulo

Comparison

OpMeaning
==, !=equality, inequality
<, >, <=, >=ordering

Logical

OpMeaning
&&logical AND
||logical OR
not(x)logical NOT (function)

Special operators

OpMeaningExample
|>pipe-forwardx |> f becomes f(x)
<-send/pushsubject <- value
?.safe callexpr?.field (None propagation)
?:elvisexpr ?: default (unwrap with fallback)

The pipe operator inserts the left side as the first argument:

x |> f           -- f(x)
x |> f(a, b)     -- f(x, a, b)
x |> f |> g      -- g(f(x))

Control Flow

if/else

if condition { then_expr }
if condition { then_expr } else { else_expr }
if x > 0 { "positive" } else if x == 0 { "zero" } else { "negative" }

match

match expr {
    | Pattern1 -> body1
    | Pattern2 if guard -> body2
    | _ -> default_body
}

The | before each arm is optional. Patterns can destructure ADTs:

match shape {
    | Circle(r) -> 3.14 * r * r
    | Rectangle(w, h) -> w * h
}

match point {
    | Point(x: xval, y: _) -> xval    -- named field destructuring
}

for loop

for item in collection {
    @ print(show(item))
}

Works with List, Stream, and subjects.

Closures

|x| x * 2                       -- single parameter
|x, y| x + y                    -- multiple parameters
|x: Int, y: Float| x + y        -- with type annotations

Closures capture their enclosing environment.

Built-in Functions (Quick Reference)

For the complete standard library with all ~70 builtins, see stdlib.md.

Display

FunctionSignatureDescription
showa -> StringConvert any value to string

List operations

FunctionSignatureDescription
lengthList(a) -> IntList length
headList(a) -> aFirst element
tailList(a) -> List(a)All but first
push(List(a), a) -> List(a)Append element
concat(List(a), List(a)) -> List(a)Concatenate
reverseList(a) -> List(a)Reverse
map(List(a), a -> b) -> List(b)Map function
filter(List(a), a -> Bool) -> List(a)Filter
foldl(List(a), b, (b, a) -> b) -> bLeft fold
range(Int, Int) -> List(Int)Range [start, end)

Math

FunctionSignatureDescription
absInt -> IntAbsolute value
sqrtFloat -> FloatSquare root
pow(Float, Float) -> FloatExponentiation
roundFloat -> IntRound to nearest
floorFloat -> IntFloor
max_int(Int, Int) -> IntMaximum
min_int(Int, Int) -> IntMinimum
clamp(Int, Int, Int) -> IntClamp to range
to_floatInt -> FloatConvert to float

String

FunctionSignatureDescription
string_lengthString -> IntUnicode scalar length
starts_with(String, String) -> BoolPrefix check

Option/Result

FunctionSignatureDescription
unwrap_or(Option(a), a) -> aUnwrap with default
is_someOption(a) -> BoolCheck if Some
is_noneOption(a) -> BoolCheck if None

Logic

FunctionSignatureDescription
notBool -> BoolLogical NOT
assertBool -> ()Runtime assertion
identitya -> aIdentity function

Comments

-- Line comment

----
Block comment
can span multiple lines
----