Standard Library

Aria's standard library is organized into two tiers. The design philosophy: the 90% case should be one function call.

Tier 0: Built-in (No Import Needed)

These are available everywhere without any use statement:

Output

println("hello")          // print with newline
print("no newline")       // print without newline

Lists

nums := [1, 2, 3, 4, 5]
nums.len()                          // 5
nums.map(fn(x) => x * 2)           // [2, 4, 6, 8, 10]
nums.filter(fn(x) => x > 3)        // [4, 5]
nums.fold(0, fn(a, b) => a + b)    // 15
nums.sort()                         // [1, 2, 3, 4, 5]
nums.reverse()                      // [5, 4, 3, 2, 1]
nums.enumerate()                    // [(0,1), (1,2), ...]
nums.contains(3)                    // true
nums.append(6)                      // [1, 2, 3, 4, 5, 6]
nums.join(", ")                     // "1, 2, 3, 4, 5"

Maps and Sets

m := Map{"a": 1, "b": 2}
m.contains("a")    // true
m.keys()           // ["a", "b"]
m.values()         // [1, 2]

s := Set{1, 2, 3}
s.contains(2)      // true

Option and Result

type Option[T] = Some(T) | None
type Result[T, E] = Ok(T) | Err(E)

// Sugar: T? means Option[T]
// Sugar: T ! E means Result[T, E]

Strings

s := "hello, world"
s.len()              // byte length
s.split(",")         // ["hello", " world"]
s.trim()             // strip whitespace
s.contains("world")  // true
s.replace("o", "0")  // "hell0, w0rld"
s.toUpper()          // "HELLO, WORLD"
s.toLower()          // "hello, world"
s[2..5]              // "llo" (zero-copy slice)

Ranges

0..10     // exclusive: 0 to 9
0..=10    // inclusive: 0 to 10

Tier 1: Core Modules (One-Word Import)

use io, net, json, db, time, crypto, log, math

io — File I/O

use io

content := io.readFile("data.txt")?
io.writeFile("out.txt", content)?

file := io.open("log.txt", io.Append)?
defer file.close()
file.write("entry\n")?

line := io.stdin.readLine()?

net — Networking

use net

// TCP networking
listener := net.listen(":8080")?
conn := listener.accept()?

// HTTP server
net.serve(":8080", fn(req) => {
    Response{status: 200, body: "hello"}
})

// HTTP client
resp := net.get("https://api.example.com/users")?
resp := net.post(url, body: jsonData, headers: headers)?

json — JSON

use json

// Encode (type must derive Json)
data := json.encode(myStruct)?

// Decode
cfg := json.decode[Config](jsonString)?

// Streaming
stream := json.stream(reader)?

db — Database

use db

conn := db.connect("postgres://localhost/mydb")?
defer conn.close()

users := conn.query[User]("SELECT * FROM users WHERE active = $1", true)?
conn.exec("INSERT INTO logs (msg) VALUES ($1)", "hello")?

time — Time & Duration

use time

now := time.now()
time.sleep(2s)
formatted := now.format("2006-01-02")
parsed := time.parse("2024-01-15", "2006-01-02")?

crypto — Cryptography

use crypto

hash := crypto.sha256(data)
hashed := crypto.hashPassword(password)?
ok := crypto.verifyPassword(password, hashed)?

log — Logging

use log

log.info("server started on port {port}")
log.warn("retry attempt {n}")
log.error("connection failed: {err}")
log.debug("request payload: {body}")

math — Mathematics

use math

math.sqrt(144.0)    // 12.0
math.sin(math.PI)   // ~0.0
math.abs(-5)        // 5
math.max(a, b)
math.min(a, b)

Serialization with Derives

Combine derives with the json module for zero-boilerplate serialization:

type User {
    id: i64
    name: str
    email: str
} derives [Json]

user := User{id: 1, name: "Alice", email: "alice@example.com"}
jsonStr := json.encode(user)?
decoded := json.decode[User](jsonStr)?

Next Steps