#!/usr/bin/env catnip
# Unions taggees (ADT)
#
# Lancer via le CLI Python (mode VM par defaut ou -x ast) :
# python -m catnip docs/examples/advanced/11_unions.cat
# Le binaire standalone catnip-run ne supporte pas encore les unions.
print("=> Declaration et construction")
union Option {
Some(value);
None;
}
x = Option.Some(42)
y = Option.None
print("Option.Some(42).value =", x.value)
print("Option.None =", y)
print()
print("=> Pattern matching avec payload")
describe = (opt) => {
match opt {
Option.Some{value} => { f"got {value}" }
Option.None => { "nothing" }
}
}
print(describe(Option.Some(7)))
print(describe(Option.None))
print()
print("=> Variantes nullaires + payload melangees")
union Event {
Click(x, y);
KeyPress(code);
Quit;
}
handle = (event) => {
match event {
Event.Click{x, y} => { f"click at {x},{y}" }
Event.KeyPress{code} => { f"key {code}" }
Event.Quit => { "bye" }
}
}
print(handle(Event.Click(10, 20)))
print(handle(Event.KeyPress(65)))
print(handle(Event.Quit))
print()
print("=> Egalite structurelle")
print("Option.Some(1) == Option.Some(1):", Option.Some(1) == Option.Some(1))
print("Option.Some(1) == Option.Some(2):", Option.Some(1) == Option.Some(2))
union Box { A(v); B(v) }
print("Box.A(1) == Box.B(1):", Box.A(1) == Box.B(1))
print()
print("=> Generiques (parses, non verifies)")
union Result[T, E] {
Ok(value: T);
Err(error: E);
}
divide = (a, b) => {
if b == 0 { Result.Err("division by zero") }
else { Result.Ok(a / b) }
}
unwrap = (r, default) => {
match r {
Result.Ok{value} => { value }
Result.Err{error} => { default }
}
}
print("divide(10, 2):", unwrap(divide(10, 2), 0))
print("divide(10, 0):", unwrap(divide(10, 0), -1))
print()
print("=> Machine a etats avec donnees")
union State {
Idle;
Loading(progress);
Ready(data);
Failed(reason);
}
step = (state, event) => {
match state {
State.Idle => {
if event == "start" { State.Loading(0) }
else { State.Idle }
}
State.Loading{progress} => {
if event == "tick" { State.Loading(progress + 10) }
elif event == "done" { State.Ready("payload") }
elif event == "error" { State.Failed("network") }
else { State.Loading(progress) }
}
State.Ready{data} => { State.Ready(data) }
State.Failed{reason} => { State.Failed(reason) }
}
}
s = State.Idle
s = step(s, "start")
s = step(s, "tick")
s = step(s, "tick")
print("apres start+tick+tick:")
match s {
State.Loading{progress} => { print(" loading", progress, "%") }
_ => { print(" autre") }
}
s = step(s, "done")
print("apres done:")
match s {
State.Ready{data} => { print(" ready:", data) }
_ => { print(" autre") }
}