Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Effects

A function’s effect row, after !, lists everything it may do besides return a value. The checker makes the row exact: an undeclared effect is E_EFFECT_MISSING, and a declared one the body never performs is W_EFFECT_UNUSED. Effects flow through calls and lambdas, and a catch or handle that covers an effect removes it from the row. Effects and Errors teaches them.

Built-in effects

EffectIntroduced by
loglog(msg). An ordinary effect with one operation, so a handle can capture it
fail[E]raise e with e: E, opt.ok_or(e), res.get, or calling a function with fail[E]
divA while loop, which may not terminate
fsread_file write_file append_file remove_file list_dir read_bytes write_bytes mkdir mkdir_all remove_dir rename exists is_dir file_size modified_ms copy_file symlink read_link is_symlink file_mode set_mode open_file with_file read_bin write_bin, the File methods, gzip and zstd compress_file decompress_file, csv.read fold, config.load
ioread_line read_lines (stdin) and eprint (stderr)
procrun_cmd exit proc.spawn, and the Proc methods
timenow_ms mono_ns sleep_ms now time_zone local_zone, uuid.v7
envenv_var args, config.load
nethttp.get post send fetch download serve serve_with (Networking)
dbSQLite: db.open exec query one opt tx migrate (Databases)
randcrypto.random token key seal hash_password keypair, uuid.v4 v7
concCreating or using an Atomic[Int] or a Chan[T]
yield[T]yield(x) with x: T, which makes a generator
db.read[S], db.write[S]db.get and db.scan, and db.put and db.del, on the store S
ffiCalling an extern fn
devLaunching a kernel fn, dev_f32 dev_f64 dev_i32 dev_u32 dev_int, DevBuf.to_list, gpu_sync()
unsafeRaw memory (alloc free load store offset) and inline asm, in profile sys and bare. Discharge it with an unsafe "reason" line
mmio, staticHardware registers and module statics in profile bare

A user effect can’t take one of these names (E_DUPLICATE). A package may still export a function named like one (pub fn fail): in an effect row, the name is always the built-in effect.

Your own effects

FormMeaning
effect ask() -> IntOne operation with the effect’s name. Callers declare ! ask
effect state + indented get() -> Int, put(v: Int)Several operations
effect emit[T](x: T)A generic effect: emit[Int], emit[Str]
Effect row parameter efn map_all[A, B, e](xs: List[A], f: A -> B ! e) -> List[B] ! e performs what f performs
Row parameter shared by argumentsfn twice[e](a: (Int -> Int ! e) -> (Int -> Int ! e), b: (Int -> Int ! e) -> (Int -> Int ! e), f: Int -> Int ! e): e is the union of what the arguments perform, so a may add log and b add time
fail[E] next to a row parameterfn rescue[E, e](next: Int -> Int ! fail[E], e) -> (Int -> Int ! e): E is the argument’s error type and e the rest of its row, so a wrapper that catches E leaves only e

handle e with one | op(x) => arm per operation, and an optional | return(r) => arm, gives operations meaning. resume(v) continues at the operation, at most once per arm. An arm that doesn’t resume ends the whole handle. An arm runs outside its own handler, so effects it performs go to the next one out.

Where effects are allowed

ContextAllowed
Contracts (pre, post, where)None: contracts are pure
Functions passed to Secret.map, check, validateNone
par tasksNot log or handled effects (E_PAR_EFFECT)
Service handlersDeployed: db.*, log, div, fail, time, env; not fs, io, proc or net (E_EP_EFFECT). With http.serve: anything but db.* and user-defined effects (E_SERVE_EFFECT)
Kernelsdev only (E_KERNEL_EFFECT)
profile barediv, unsafe, mmio and static
extern fnExactly ffi
Impl methodsThe trait method’s row or fewer (E_IMPL_EFFECT)

In a deployed service, the effects of each handler become its IAM policy: db.read[Todos] grants GetItem and Scan on that table only where the handler uses them. See the CRUD tutorial.