Data Types

Lambda Script has a rich set of primitive and composite types:

Primitives

42              // int (56-bit signed)
3.14            // float (64-bit)
123.45n         // decimal (arbitrary precision)
"hello"         // string (UTF-8)
'symbol'        // symbol (interned identifier)
true false      // bool
null            // null
t'2025-04-01'   // datetime
b'\xDEADBEEF'   // binary

Collections

[1, 2, 3]                   // array
{name: "Alice", age: 30}    // map
<div class: "card"; "text"> // element (markup literal)
1 to 10                     // range (inclusive)

Indexing & Slicing

arr[0]            // first element
arr[1 to 3]       // slice (indices 1, 2, 3)
map.key           // field access
"hello"[1 to 3]   // "ell" — string slicing

Variables & Bindings

// Immutable bindings (default)
let x = 42
let name: string = "Lambda"

// Let expressions (inline bindings)
(let a = 1, b = 2, a + b)   // 3

// Mutable variables (in procedural functions)
pn main() {
    var count = 0
    count = count + 1
}

Pipe Operator & Data Pipelines

The pipe operator | is Lambda's signature feature — fluent, set-oriented data transformations. Use ~ to reference the current item:

// Map: apply a transformation to every element
[1, 2, 3] | ~ * 2                    // [2, 4, 6]

// Extract fields
users | ~.name                        // ["Alice", "Bob", "Carol"]

// Filter with 'that'
[1, 2, 3, 4, 5] that ~ > 3           // [4, 5]

// Chain operations: filter → map → aggregate
users that ~.age >= 18 | ~.name | len // count adult names

// Pipe spread in array literals
[0, [1, 2, 3] | ~ * 10, 99]          // [0, 10, 20, 30, 99]

Vector Arithmetic

Scalar operations automatically broadcast over collections:

1 + [2, 3]          // [3, 4]
[1, 2] * 2          // [2, 4]
[1, 2] + [3, 4]     // [4, 6]
[1, 2] ^ 2          // [1, 4]

For-Expressions

SQL-like comprehensions with where, order by, limit, offset:

// Filter and transform
for (x in data where x > 0) x * 2

// With local bindings
for (x in data, let sq = x * x where sq > 10) sq

// Sorting and pagination
for (x in items order by x.price desc limit 5) x.name

// Multi-source comprehension
for (x in xs, y in ys where x + y > 10) {x, y}

Type System

Lambda has a rich type system with inference and explicit annotations, similar to and beyond TypeScript:

// Type annotations
let x: int = 42
let items: [string] = ["a", "b"]

// Union and optional types
type Result = int | error
type Name = string?          // string | null

// Type declarations
type User = {name: string, age: int}
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"

Object Types

type Point {
    x: float, y: float;
    fn distance(other: Point) =>
        math.sqrt((x - other.x)**2 + (y - other.y)**2)
}

type Circle : Point { radius: float; }  // inheritance

let p = {Point x: 3.0, y: 4.0}          // object literal
p.distance({Point x: 0.0, y: 0.0})      // method call
p is Point                                // true (nominal)

Element Type Patterns

// Schema types for document structures
type Link = <a href: string; string>
type Article = <article title: string; string, Section*>
type ImgTag = <img src: string, alt: string>

Functions

// Pure functions (fn)
fn add(a: int, b: int) => a + b
fn greet(name: string) => "Hello, " ++ name ++ "!"

// Lambda expressions
let double = (x) => x * 2
let add3 = fn(a, b, c) => a + b + c

// Procedural functions with mutation (pn)
pn process() {
    var total = 0
    for i in range(0, 10) {
        total = total + i
    }
    print(total)
}

Pattern Matching

fn describe(x) => match x {
    case null:             "nothing"
    case 0:                "zero"
    case 1 to 9:           "small number"      // range
    case int that (~ > 9): "big number"        // type + constraint
    case string:           "text: " ++ ~        // type
    case [int]:            "int array"          // collection type
    default:               "something else"
}

Query Operator

The ? query operator searches data trees by type or structure:

html?<img>                    // all <img> descendants
html?<div class: string>      // <div>s with a class attribute
data?{status: "ok"}           // maps where status == "ok"
html[body][div]?<a>           // direct path then recursive

Error Handling

// Functions that can fail return T^E (value ^ error)
fn divide(a: float, b: float) float^error =>
    if b == 0 { raise "division by zero" }
    else { a / b }

// Propagate errors with ?
fn compute(x: float) float^error => {
    let r = divide(100, x)?    // propagates error if divide fails
    r * 2
}

// Destructure with let a^err
let result^err = divide(10, 0)
if err { print("Error: " ++ err.message) }
else { print("Result: " ++ str(result)) }

Document Processing

Lambda's signature capability — treat documents as structured data:

Markup Literals

let page = <html
    <head
        <title "My Page">
        <style "body { font-family: sans-serif; }">
    >
    <body
        <h1 "Welcome">
        <p "Lambda treats " <strong "documents"> " as data.">
    >
>

format(page, 'html')    // render to HTML string

Multi-Format Parsing

let md   = input("readme.md",    'markdown')
let html = input("page.html",    'html')
let json = input("data.json",    'json')
let yaml = input("config.yaml",  'yaml')
let csv  = input("data.csv",     'csv')
let tex  = input("paper.tex",    'latex')

Format Conversion

// Direct format conversion
format(data, 'json')       // to JSON string
format(data, 'yaml')       // to YAML string
format(data, 'markdown')   // to Markdown string