ilusm.dev

How-To Guides

Task-oriented cookbook. Each recipe is a complete, runnable program.

Parse and generate JSON

use json

# Decode
raw  = "{\"name\": \"ilusm\", \"count\": 42, \"tags\": [\"lang\", \"vm\"]}"
data = json.dec(raw)
prn(data.name)       # ilusm
prn(data.count)      # 42
prn(data.tags[0])    # lang

# Encode
obj = {lang: "ilusm", stable: tru, version: 2}
out = json.enc(obj)
prn(out)

Read and write files

use fs
use txt

# Write
fs.wr("hello.txt", "hello from ilusm\n")

# Read
content = fs.rd("hello.txt")
prn(content)

# Read lines (split on newlines)
lines = txt.spl(fs.rd("hello.txt"), "\n")
prn(len(lines))

# Append
fs.app("log.txt", "event at " + str(__sys_now()) + "\n")

# Check existence
if fs.ex("config.json"):
  cfg = json.dec(fs.rd("config.json"))
  prn(cfg)

Build a CLI tool

use txt

# Arguments are available via __sys_argv()
argv = __sys_argv()

if len(argv) == 0:
  prn("usage: mytool <command> [options]")
  __sys_exit(1)

cmd = argv[0]

if cmd == "hello":
  name = if len(argv) > 1: argv[1] | "world"
  prn("hello, " + name + "!")

| if cmd == "upper":
  if len(argv) < 2:
    prn("usage: mytool upper <text>")
    __sys_exit(1)
  prn(txt.upr(argv[1]))

| prn("unknown command: " + cmd)

Handle errors gracefully

use eru

# Pattern 1: try returns {val, err} record
result = try(\() risky_operation())
if result.err != nil:
  prn("operation failed, using default")
  result = {val: default_value, err: nil}

# Pattern 2: eru.from_try normalizes try result
t = try(\() parse_config("config.json"))
safe = eru.from_try(t)
if safe.err != nil:
  prn("config error: " + eru.txt(safe.err))
  __sys_exit(1)
cfg = safe.val

# Pattern 3: guard with early return
load_config(path) =
  if !fs.ex(path): ret nil
  raw = fs.rd(path)
  if raw == nil: ret nil
  json.dec(raw)

Work with lists

use trl

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Map - transform every element
doubled = trl.map(nums, \(x) x * 2)
prn(doubled)   # [2 4 6 8 10 12 14 16 18 20]

# Filter - keep matching elements
evens = trl.fil(nums, \(x) x % 2 == 0)
prn(evens)     # [2 4 6 8 10]

# Fold - reduce to a single value
total = trl.fld(nums, 0, \(acc, x) acc + x)
prn(total)     # 55

# Sort
sorted = trl.srt([3, 1, 4, 1, 5, 9, 2, 6])
prn(sorted)

# Sort by key
people = [{name: "charlie"}, {name: "alice"}, {name: "bob"}]
by_name = trl.srtby(people, \(p) p.name)
trl.each(by_name, \(p) prn(p.name))

Work with strings

use txt

s = "  Hello, World!  "

prn(txt.trm(s))                    # Hello, World!
prn(txt.upr(s))                    # HELLO, WORLD!
prn(txt.lwr(s))                    # hello, world!
prn(txt.spl("a,b,c", ","))         # ["a" "b" "c"]
prn(txt.has(s, "World"))           # tru
prn(txt.rep(s, "World", "ilusm"))  # Hello, ilusm!
prn(txt.sub(s, 2, 7))              # Hello

# Join a list of strings
parts = ["hello", "world", "ilusm"]
joined = txt.join(parts, ", ")
prn(joined)   # hello, world, ilusm

Parse CSV

use csv

raw = "name,age,city\nalice,30,london\nbob,25,paris"
rows = csv.dec(raw)

# rows[0] is the header
# rows[1..] are data rows
trl.each(rows, \(row) prn(row))

Make HTTP requests

use net
use json

# GET
resp = net.get("https://httpbin.org/json")
prn("status: " + str(resp.status))
data = json.dec(resp.body)
prn(data)

# POST JSON
body = json.enc({name: "ilusm", version: 2})
resp = net.post("https://httpbin.org/post", body, {
  "Content-Type": "application/json"
})
prn(resp.status)

Debug a program

use pfl
use dbg

# Profile a block
r = pfl.pflnm("my_block", \() expensive_operation())
prn(r)

# Inspect variables via debug syscall
dbgin("x")

# Enable tracing
dbgtr()

# Assert with break
dbgas(len(xs) > 0, "list must not be empty")