Lambda Data: Literals and Collections

July 2, 2026 · View on GitHub

This document covers Lambda's literal values, collection types, and expressions for composing data structures.

Related Documentation:


Table of Contents

  1. Data Types Overview
  2. Primitive Literals
  3. Path Literals
  4. Collections
  5. Collection Comprehensions
  6. Data Composition Expressions

Data Types Overview

Lambda Script has a rich type system with both primitive and composite types:

Primitive Types

TypeDescriptionExample
nullNull/void valuenull
boolBoolean valuestrue, false
int56-bit signed integers42, -123
float64-bit floating point3.14, 1.5e-10
i8 i16 i32Sized signed integers42i8, 1000i16
u8 u16 u32Sized unsigned integers255u8, 60000u16
i6464-bit signed (alias for int64)100i64
u6464-bit unsigned integer1000u64
f16 f32Sized floating point0.5f16, 3.14f32
f6464-bit float (alias for float)2.7f64
decimalArbitrary precision decimal123.456n,456.789N
stringUTF-8 text strings"hello"
symbolInterned identifiers'symbol'
binaryBinary datab'\xDEADBEEF'
datetimeDate and time valuest'2025-01-01'

Composite Types

TypeDescriptionExample
arrayOrdered collections[1, 2, 3]
mapKey-value mappings{key: "value"}
elementStructured markup elements<tag attr: value; content>
rangeNumeric ranges1 to 10
pathFile paths and URLs/etc.hosts, https.'api.example.com'
functionFunctions(x) => x + 1
typeType descriptorsint, string

Special Types

  • any — Any type (top type)
  • error — Error values
  • number — Numeric union type (int | float)

Primitive Literals

Boolean and Null Literals

true
false
null

Lambda also treats empty text identifiers as null: the empty string literal "" and the empty symbol literal '' are normalized to null. For user data, treat string and symbol values as non-empty, with null representing the empty case.

Numeric Literals

// Integers
42
-123
0

// Floats
3.14
-2.5
1.5e-10
1e6
inf
nan
-inf

// Decimals (arbitrary precision)
123.456n       // decimal128
-789.012N      // unlimited precision decimal

// Sized integers (postfix suffix)
42i8           // 8-bit signed  [-128, 127]
1000i16        // 16-bit signed [-32768, 32767]
100000i32      // 32-bit signed [-$2^{31}$, $2^{31}$-1]
100i64         // 64-bit signed (alias for int64)
255u8          // 8-bit unsigned [0, 255]
60000u16       // 16-bit unsigned [0, 65535]
3000000000u32  // 32-bit unsigned [0, $2^{32}$-1]
1000u64        // 64-bit unsigned [0, $2^{64}$-1]

// Sized floats (postfix suffix)
0.5f16         // 16-bit float (half precision)
3.14f32        // 32-bit float (single precision)
2.7f64         // 64-bit float (alias for float)

Sized numeric types use a postfix suffix on numeric literals. Types i8 through u32 and f16/f32 are packed inline in the 64-bit Item representation (zero heap allocation). Types i64, u64, and f64 are heap-allocated.

Overflow behavior: Sized integer arithmetic follows a Go-like fixed-width model and wraps deterministically in the result width:

127i8 + 1i8    // -128 (wraps)
255u8 + 1u8    // 0 (wraps)

Special float values:

  • inf — Positive infinity
  • -inf — Negative infinity
  • nan — Not a number

String Literals

String literals use double quotes. Single quotes do not create strings in Lambda; they create symbol values (see Symbol Literals). The empty string literal "" is normalized to null; for user data, use null to represent the empty case.

// Basic strings
"hello world"
"multiline strings
can span multiple lines"
""                  // null

// Escape sequences
"line 1\nline 2"
"tab\there"
"quote: \"hello\""

Supported escape sequences:

EscapeCharacter
\nNewline
\tTab
\rCarriage return
\\Backslash
\"Double quote

String Indexing and Slicing

Strings are indexable by character position (0-based). Both single-character access and range slicing are supported:

let s = "hello";
s[0]              // "h"  — first character
s[4]              // "o"  — last character
s[-1]             // "o"  — negative index counts from end

// Range subscript: str[a to b] (inclusive both ends)
s[0 to 4]         // "hello"  — full string
s[1 to 3]         // "ell"   — substring
s[0 to 0]         // "h"     — single character via range

// UTF-8 aware: indices are character positions, not byte offsets
let c = "café";
c[2 to 3]         // "fé"   — works correctly with multi-byte characters

// Character ↔ code point conversion
ord("A")           // 65    — Unicode code point of first character
chr(65)            // "A"   — string from Unicode code point
ord("é")           // 233
chr(128512)        // "😀"

Symbol Literals

Symbols are interned identifiers, often used as keys or tags:

'identifier'
'symbol-name'
'CamelCase'
'json'
'markdown'
''                  // null

The empty symbol literal '' is normalized to null; for user data, use null to represent the empty case.

Symbol vs String:

  • Symbols are interned (only one copy exists in memory)
  • Comparison is O(1) pointer equality
  • Used for type tags, format identifiers, map keys
  • Single quotes are not alternate string syntax: 'name' is a symbol, "name" is a string, and 'name' == "name" is false
  • Use string(sym) or symbol(str) when crossing the boundary explicitly

Symbol Indexing and Slicing

Like strings, symbols support character indexing and range slicing. The result is always a symbol:

let sym = 'hello';
sym[0]             // 'h'   — single character (symbol)
sym[1 to 3]        // 'ell'  — substring (symbol)
sym[0 to 4]        // 'hello' — full symbol

Binary Literals

// Hexadecimal
b'\xDEADBEEF'
b'\xA0FE af0d'

// Base64
b'\64A0FE'
b'\64A0FE gh8='
b'\64A0FE gh=='

DateTime Literals

DateTime literals use the t'...' syntax:

// Dates
t'2025'           // Year only
t'2025-06'        // Year-month
t'2025-04-26'     // Full date
t'-1000-12-25'    // Historical dates

// Times
t'10:30'          // Hour:minute
t'10:30:45'       // Hour:minute:second
t'10:30:45.123'   // With milliseconds
t'10:30+08'       // With timezone

// Date-time combinations
t'2025-05-01 10:30'
t'2025-05-01T14:30:00Z'

DateTime Sub-Types

Lambda has three datetime-related types in a sub-type hierarchy:

         datetime
        /        \
     date        time
  • date — Date-only values (year, month, day)
  • time — Time-only values (hour, minute, second, millisecond)
  • datetime — Full date and time values
// Type checking
t'2025-04-26' is date        // true  (date-only precision)
t'2025-04-26' is datetime    // true  (date <: datetime)
t'10:30:00' is time          // true  (time-only precision)
t'10:30:00' is datetime      // true  (time <: datetime)
t'2025-04-26T10:30' is date  // false (has both date and time)
t'2025-04-26T10:30' is time  // false (has both date and time)

DateTime Member Properties

Access datetime components using dot notation:

Date Properties:

let dt = t'2025-04-26T10:30:45.123+05:30'

dt.year          // 2025       (int)
dt.month         // 4          (int, 1–12)
dt.day           // 26         (int, 1–31)
dt.weekday       // 6          (int, 0=Sunday, 6=Saturday)
dt.yearday       // 116        (int, 1–366, day of year)
dt.week          // 17         (int, ISO week number 1–53)
dt.quarter       // 2          (int, 1–4)

Time Properties:

dt.hour          // 10         (int, 0–23)
dt.minute        // 30         (int, 0–59)
dt.second        // 45         (int, 0–59)
dt.millisecond   // 123        (int, 0–999)

Timezone Properties:

dt.timezone      // 330        (int, offset in minutes from UTC)
dt.utc_offset    // '+05:30    (symbol, formatted offset)
dt.is_utc        // false      (bool)

Meta Properties:

dt.unix          // 1745635845123 (int, Unix timestamp in milliseconds)
dt.is_date       // true       (bool, has date component)
dt.is_time       // true       (bool, has time component)
dt.is_leap_year  // false      (bool)
dt.days_in_month // 30         (int, days in the datetime's month)

Extraction & Conversion Properties:

dt.date          // t'2025-04-26'          (extract date part)
dt.time          // t'10:30:45'            (extract time part)
dt.utc           // t'2025-04-26T05:00:45Z' (convert to UTC)
dt.local         // convert to local timezone

DateTime Member Functions

Formatting:

let dt = t'2025-04-26T10:30:45'

// Custom format patterns
dt.format("YYYY-MM-DD")              // "2025-04-26"
dt.format("DD/MM/YYYY")              // "26/04/2025"
dt.format("hh:mm A")                 // "10:30 AM"
dt.format("YYYY-MM-DD hh:mm:ss")     // "2025-04-26 10:30:45"
dt.format("MMM DD, YYYY")            // "Apr 26, 2025"

// Predefined format names (symbol argument)
dt.format('iso')                      // "2025-04-26T10:30:45"
dt.format('human')                    // "April 26, 2025 10:30 AM"
dt.format('date')                     // "2025-04-26"
dt.format('time')                     // "10:30:45"

Format Pattern Tokens:

TokenMeaningExample
YYYY4-digit year2025
YY2-digit year25
MM2-digit month04
MMonth without padding4
MMMAbbreviated month nameApr
MMMMFull month nameApril
DD2-digit day26
DDay without padding26
dddAbbreviated weekdaySat
ddddFull weekdaySaturday
hh2-digit hour (24h)10
hHour without padding10
HH2-digit hour (12h)10
mm2-digit minute30
ss2-digit second45
SSS3-digit millisecond000
AAM/PMAM
ZUTC offset+00:00
ZZUTC offset compact+0000

DateTime Constructors

datetime(...) — Full Constructor:

// Current date and time
datetime()                           // current UTC datetime

// Parse from string
datetime("2025-04-26T10:30:00")      // parse ISO 8601 string

// From components
datetime(2025, 4, 26)                // date only: t'2025-04-26'
datetime(2025, 4, 26, 10, 30)        // date + time: t'2025-04-26 10:30'
datetime(2025, 4, 26, 10, 30, 45)    // full: t'2025-04-26 10:30:45'

// From Unix timestamp
datetime(1714100000)                 // from Unix timestamp (seconds)

// From map
datetime({year: 2025, month: 4, day: 26, hour: 10, minute: 30})

date(...) — Date Constructor:

// Current date
date()                   // same as today()

// Extract from datetime
date(some_datetime)      // extract date part

// From components
date(2025, 4, 26)        // t'2025-04-26'
date(2025, 4)            // t'2025-04'   (year-month)
date(2025)               // t'2025'      (year only)

// Parse from string
date("2025-04-26")       // parse date string

time(...) — Time Constructor:

// Current time
time()                   // same as justnow()

// Extract from datetime
time(some_datetime)      // extract time part

// From components
time(10, 30)             // t'10:30'
time(10, 30, 45)         // t'10:30:45'
time(10, 30, 45, 500)    // t'10:30:45.500'

// Parse from string
time("10:30:45")         // parse time string

Related Functions:

today()                  // current date (DATE_ONLY precision)
justnow()                // current time (TIME_ONLY precision)

Path Literals

The path type represents file system paths and URLs in a unified, platform-independent way. Paths use dot notation for segment separation.

Path Syntax

// Absolute file paths (start with /)
/etc.hosts                    // /etc/hosts
/home.user.documents          // /home/user/documents
/usr.local.bin.lambda         // /usr/local/bin/lambda

// Relative paths (start with . or ..)
.config.json                  // ./config.json
.src.main.ls                  // ./src/main.ls
..parent.file                 // ../parent/file

// Quoted segments (for names containing dots or special chars)
/var.log.'app.log'            // /var/log/app.log
.data.'my-file.json'          // ./data/my-file.json
/home.user.'Documents and Settings'  // Spaces in names

// HTTP/HTTPS URLs
http.api.github.com.users     // http://api.github.com/users
https.example.com.data        // https://example.com/data
https.httpbin.org.json        // https://httpbin.org/json

// System paths
sys.env.HOME                  // Environment variable $HOME
sys.env.PATH                  // Environment variable $PATH
sys.platform                  // Operating system platform

// Wildcards in paths
.src.*                        // Single-level: all in ./src
.test.**                      // Recursive: all under ./test
/var.log.'*.log'              // Pattern in filename

Path Schemes

SchemeRoot SyntaxExampleResolves To
Absolute file//etc.hosts/etc/hosts
Relative (current)..src.main./src/main
Relative (parent)....shared.lib../shared/lib
HTTPhttphttp.'api.example.com'http://api.example.com
HTTPShttpshttps.'secure.api'https://secure.api
Systemsyssys.env.PATHSystem environment variable

Wildcards

Paths support glob-style wildcards for pattern matching:

// Single-level wildcard (*)
.src.*                        // All items directly in ./src
/var.log.*                    // All items in /var/log

// Recursive wildcard (**)
.test.**                      // All items recursively under ./test
/home.user.documents.**       // All files recursively

Path Concatenation

Paths can be concatenated using the ++ operator:

let base = /home.user
let config = base ++ "config" ++ "settings.json"
// Result: /home.user.config.'settings.json'

let project = .src
let file = project ++ "main.ls"
// Result: .src.'main.ls'

Path vs String

FeaturePathString
Syntax/etc.hosts"/etc/hosts"
Typepathstring
URL supportNativeRequires parsing
WildcardsBuilt-in (*, **)Manual
Lazy loadingYesNo
Platform-independentYesSeparator varies
// Path literal - cross-platform, supports URLs
let p = /home.user.config

// String - platform-specific
let s = "/home/user/config"

// Both work with input()
let data1 = input(p, 'json')
let data2 = input(s, 'json')

Path Operations

// Check existence
exists(/etc.hosts)            // true or false
exists(.config.json)          // true or false

// Load content
let content = input(/etc.hosts, 'text')    // Load file content
let data = input(https.api.example.com.data, 'json')  // Fetch URL

System Info Paths (sys.*)

The sys path scheme provides cross-platform access to system information. Values are lazily resolved — data is only fetched when accessed.

System Info Categories

PathTypeDescription
sys.osMapOperating system information
sys.cpuMapCPU/processor information
sys.memoryMapMemory statistics
sys.procMapProcess information
sys.homePathUser home directory
sys.tempPathSystem temporary directory
sys.timeMapCurrent time and timezone
sys.lambdaMapLambda runtime information
sys.localeMapLocale settings

OS Information (sys.os.*)

sys.os.name              // "Darwin", "Linux", "Windows"
sys.os.version           // "23.2.0", "6.5.0", "10.0.22631"
sys.os.kernel            // Full kernel version string
sys.os.platform          // "darwin", "linux", "windows"
sys.os.hostname          // Machine hostname

CPU Information (sys.cpu.*)

sys.cpu.model            // "Apple M2", "Intel Core i7-12700K"
sys.cpu.cores            // Number of CPU cores (e.g., 8)
sys.cpu.architecture     // "arm64", "x86_64"

Memory Information (sys.memory.*)

sys.memory.total         // Total memory in bytes
sys.memory.free          // Free memory in bytes
sys.memory.used          // Used memory in bytes

Process Information (sys.proc.*)

// Current process
sys.proc.self.pid        // Current process ID
sys.proc.self.ppid       // Parent process ID
sys.proc.self.uid        // User ID (Unix)
sys.proc.self.gid        // Group ID (Unix)
sys.proc.self.argv       // Command-line arguments as list
sys.proc.self.cwd        // Current working directory (as Path)
sys.process              // Alias for sys.proc.self

// Environment variables
sys.proc.self.env        // Map of all environment variables
sys.proc.self.env.PATH   // Specific variable: $PATH
sys.proc.self.env.HOME   // Specific variable: $HOME

// System uptime
sys.proc.uptime          // System uptime in seconds

Directory Paths (sys.home, sys.temp)

These return actual path values that can be used for file operations:

sys.home                 // User home directory (e.g., /Users/alice)
sys.temp                 // Temp directory (e.g., /tmp)

// Path composition with sys paths
let config = sys.home ++ ".config" ++ "app.json"
// Result: /Users/alice/.config.'app.json'

let tempfile = sys.temp ++ "output.txt"
// Result: /tmp.'output.txt'

Time Information (sys.time.*)

sys.time.now             // Current datetime
sys.time.zone            // Timezone name (e.g., "America/Los_Angeles")
sys.time.offset          // UTC offset in seconds

Lambda Runtime (sys.lambda.*)

sys.lambda.version       // Lambda version (e.g., "0.9.0")
sys.lambda.build         // Build date
sys.lambda.features      // List of enabled features

Full Example

// Build a system report
let report = {
    os: sys.os.name ++ " " ++ sys.os.version,
    cpu: sys.cpu.model,
    cores: sys.cpu.cores,
    memory_gb: sys.memory.total / (1024 ** 3),
    home: sys.home,
    user: sys.proc.self.env.USER
}

// Check if running on macOS
if (sys.os.platform == "darwin") {
    // macOS-specific code
}

// Access environment variables
let path_dirs = split(sys.proc.self.env.PATH, ":")

Collections

Arrays

Ordered collections:

// Array creation
[1, 2, 3]
["a", "b", "c"]
[true, false, null]

// Empty array
[]

// Mixed-type arrays
[42, "hello", 3.14, true, null]

// Nested arrays
[[1, 2], [3, 4], [5, 6]]

Array Access

let arr = [10, 20, 30];
arr[0]     // 10
arr[1]     // 20
arr[-1]    // 30 (last element)
arr[-2]    // 20 (second to last)

Array Slicing

let arr = [0, 1, 2, 3, 4, 5];
arr[1 to 4]      // [1, 2, 3, 4] — elements 1 to 4

Array Operations

len(arr)           // 3
arr ++ [4, 5]      // Concatenate: [10, 20, 30, 4, 5]
reverse(arr)       // [30, 20, 10]
sort(arr)          // [10, 20, 30]
unique([1,1,2,2])  // [1, 2]

Use ++ for list/array concatenation. The + operator is numeric vector arithmetic on arrays/lists, not append:

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

Maps

Key-value mappings with structural typing:

// Map creation
{key: "value"}
{name: "Alice", age: 30, active: true}

// Mixed key types
{"string_key": 1, symbol_key: 2}

// Nested maps
{
    user: {name: "Bob", email: "bob@example.com"},
    settings: {theme: "dark", notifications: true}
}

// Empty map
{}

// Dynamic map construction
map([k1, v1, k2, v2, ...])

Map Access

let person = {name: "Charlie", age: 25};
person.name      // "Charlie" — dot notation
person["name"]   // "Charlie" — bracket notation
person.age       // 25

// Safe key access, like JS optional chaining ?. (rerturn `null` if key missing)
person.address   // null (key doesn't exist)

Map Operations

len(person)               // 2

// Spreading a map into a new map
let wrapped = {*:person, gender: 'male'}
// {name: "Charlie", age: 25, gender: 'male'}

Elements

Structured markup elements with attributes and content, used for document processing:

// Basic element
<tag>

// Element with attributes
<div id: "main", class: "container">

// Element with content (after semicolon)
<p "Hello, world!">

// Element with attributes and content
<div class: "header"
    "Page Title"
    <span "Subtitle">
>

// Complex elements
<article title: "My Article", author: "John Doe"
    <h1 "Introduction">
    <p "This is the first paragraph.">
    <p "This is the second paragraph.">
>

Element Access

let el = <div class: "main"; "content">;
el.name      // 'div' (built-in: element tag name)
el.class     // "main" (attribute access)
el[0]        // "content" (content/child access)

Built-in Properties: Elements have a built-in .name property that returns the element's tag name as a symbol. User-defined attributes with the same name take precedence:

let custom = <div name: "custom">;
custom.name  // "custom" (user-defined takes precedence)
name(custom) // 'div' (function always returns tag)

Ranges

Numeric sequences for iteration:

// Basic ranges
1 to 10        // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
0 to 5         // [0, 1, 2, 3, 4, 5]
-2 to 2        // [-2, -1, 0, 1, 2]

// Range operations
len(1 to 10)   // 10
(1 to 5)[2]    // 3

// Range in for loops
(for (i in 1 to 5) i * i)  // [1, 4, 9, 16, 25]

Collection Comprehensions

For Expressions

For expressions iterate over collections and return new collections:

// Array iteration
(for (x in [1, 2, 3]) x * 2)  // [2, 4, 6]

// Range iteration
(for (i in 1 to 5) i * i)     // [1, 4, 9, 16, 25]

// Conditional iteration
(for (num in [1, 2, 3, 4, 5])
    if (num % 2 == 0) num else null)  // [null, 2, null, 4, null]

Extended For-Expression Clauses

For expressions support additional clauses for filtering, sorting, and limiting:

// Where clause — filter
for (x in [1, 2, 3, 4, 5] where x > 2) x
// Result: (3, 4, 5)

// Let clause — intermediate bindings
for (x in [1, 2, 3], let squared = x * x) squared + 1
// Result: (2, 5, 10)

// Order by clause — sort
for (x in [3, 1, 4, 1, 5] order by x) x
// Result: (1, 1, 3, 4, 5)

// Limit and offset — pagination
for (x in [1, 2, 3, 4, 5] limit 3 offset 1) x
// Result: (2, 3, 4)

// Combined clauses
for (x in [10, 5, 15, 20, 25, 3],
     let squared = x * x
     where x > 5
     order by squared desc
     limit 2)
  squared
// Result: (625, 400)

Pipe Expressions

The pipe operator enables fluent data transformation:

// Map over collection
[1, 2, 3] | ~ * 2           // [2, 4, 6]

// Extract field from each item
users | ~.name              // ["Alice", "Bob", ...]

// Chained transformations
[1, 2, 3, 4, 5]
    | ~ ** 2                 // square each
    | ~ + 1                 // add 1
// Result: [2, 5, 10, 17, 26]

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

Data Composition Expressions

Spread Operator

The spread operator * expands collections:

// Array spread
let a = [1, 2, 3]
let b = [0, *a, 4]        // [0, 1, 2, 3, 4]

// Map spread (merge)
let base = {x: 1, y: 2}
let extended = {*:base, z: 3}  // {x: 1, y: 2, z: 3}

// Override values
let updated = {*:base, x: 10}  // {x: 10, y: 2}

When updating an existing map or record-shaped state, spread the original value first and then list the fields to change:

let next_state = {*:state, fill: "red", font_size: 12}

A fresh map literal contains exactly the fields written in the literal. It does not copy omitted fields from any input value unless that value is explicitly spread. Prefer the {*:base, key: value} pattern for "with" constructors and state updates.

Concatenation

// Array concatenation
[1, 2] ++ [3, 4]            // [1, 2, 3, 4]

// String concatenation
"hello" ++ " world"   // "hello world"

// Path concatenation
/home.user ++ "config"      // /home.user.config

For arrays/lists, + remains element-wise numeric addition. Use ++ when the result should grow the collection.

Conditional Construction

// Conditional in collections
let items = [
    1,
    2,
    if (condition) 3 else null,  // Conditionally include
    4
]

// Conditional in maps
let config = {
    name: "app",
    debug: if (dev_mode) true else false,
    ...if (has_extra) extra_config else {}
}

Nested Data Construction

// Building complex structures
let report = {
    title: "Sales Report",
    generated: datetime(),
    summary: {
        total: sum(sales | ~.amount),
        count: len(sales),
        average: avg(sales | ~.amount)
    },
    items: (for (sale in sales) {
        id: sale.id,
        amount: sale.amount,
        formatted: "$" ++ string(sale.amount)
    })
}

Type Coercion and Conversion

Implicit Coercion

Lambda performs limited implicit coercion:

// Int to float in mixed arithmetic
1 + 2.5                     // 3.5 (int promoted to float)

// String concatenation coerces other types
"value: " ++ 42             // "value: 42"

Sized Integer Arithmetic

Sized integer arithmetic follows a Go-like fixed-width model:

// Same-width compact arithmetic preserves width and wraps
127i8 + 1i8                 // -128i8
255u8 + 1u8                 // 0u8
2147483647i32 + 1i32        // -2147483648i32
4294967295u32 + 1u32        // 0u32

// Mixed widths promote to the wider participating width
42i8 + 1000i16              // i16 result (1042)

// Mixed signed/unsigned operands promote to a type that can represent both
42i8 + 10u8                 // i16 result (52)

// Sized + standard int/float promotes to standard int or float
42i8 + 100                  // int result (142)
100i32 + 3.14               // float result (103.14)

// All sized types are compatible with number
42i8 is number              // true
3.14f32 is number           // true

Signed compact integer arithmetic wraps deterministically using two's-complement behavior in the result width. Unsigned compact integer arithmetic wraps modulo 2^N in the result width. Storage annotations keep wrapping/truncating at storage boundaries, such as compact literals, compact annotations, and compact typed-array storage.

Mixed signed/unsigned promotion uses these rules:

OperandsResult TypeRule
iN + iMi(max(N, M))wider signed width
uN + uMu(max(N, M))wider unsigned width
iN + uM, where signed width can represent all unsigned valuesthat signed typeexample: i16 + u8 -> i16
iN + uM, where the next signed width can represent bothnext wider signed typeexample: i8 + u8 -> i16, i16 + u16 -> i32, i32 + u32 -> i64
i64 + u64u64no signed Lambda integer can represent all u64 values

Sized types can be passed to functions expecting int, float, or number parameters, and vice versa.

Explicit Conversion

Use conversion functions for explicit type conversion:

// To string
string(42)                  // "42"
string(true)                // "true"
string([1, 2, 3])           // "[1, 2, 3]"

// To int
int("123")                  // 123
int(3.14)                   // 3

// To float
float("3.14")               // 3.14
float(42)                   // 42.0

// To symbol
symbol("hello")             // 'hello'

// To array
array((1, 2, 3))            // [1, 2, 3]

This document covers the foundational data types and structures in Lambda. For type system details, see Lambda Type System. For expressions and control flow, see Lambda Expressions.