OxL Reference

Step 8. Effects

Why#

If a function is called total(items), we expect it to compute a sum. But may it also go to the network, read a file or sleep for a second? In most languages you cannot know without reading the body. In OxL you see it in the signature:

EffectAllows
iofiles, processes, environment, stdout/stderr
netthe network: rpc, HTTP, actors, cluster
dbORM, std.kv, the built-in storage
timereading the clock, sleep, timers
randrandom numbers
purenone of the above

A function may call only functions whose effects are part of its own set. That makes pure functions easy to test (the result depends only on the arguments), and suspicious places where something "leaks" are found by the compiler. The same effects tell the scheduler that a function can be suspended, which is why OxL has no async/await and no function "colors".

Example#

oxl✓ checked in CI
fn double(x: i32) -> i32  pure => x * 2  // pure: no I/O and no clock

fn log(msg: str) io {  // io: writes to stdout
  print("[log] {msg}")
}

fn timed(x: i32) -> i32  io, time {  // several effects, comma separated
  log("sleeping")
  sleep(5ms)
  double(x)  // a pure function may be called from anywhere
}

fn main() io, time {
  print("{timed(21)}")
}
Output
[log] sleeping
42

Walkthrough#

  • double is pure: it can be called from anywhere, including other pure functions.
  • log declares io (the result type is omitted in the -> () form).
  • timed lists io, time: inside it calls both log and sleep. main must declare io, time too.
  • For private functions effects may be omitted - the compiler infers them. For pub(api) functions effects are mandatory: they are part of the public API, and changing effects is a breaking change.
  • A panic is not an effect: it is possible in any function.

Common mistake: an undeclared effect#

oxl✓ checked in CI
fn calc() -> i32  pure {
  sleep(1s)  // sleep requires the time effect
  42
}
error
effects

effects: calc is declared pure but calls sleep, which needs time. There are two fixes: add the effect to the signature (-> i32 time) and declare it in all callers - or remove sleep from the function that must stay pure. The second is usually better: keep the business logic pure and the I/O on the edges of the program.

Remember#

  • Effects are part of the function type; pure means no effects.
  • The caller must "allow" all effects of the callee.
  • A pure core plus a thin shell with effects is the natural architecture in OxL.

Next: modules and packages.

See also

OxL 1.0.0-beta · Documentation version 1.0.0-beta© OxwaldLink · generated from the Standard, the std sources and the guides