flan/test/programs/optionals.fln

65 lines
1.7 KiB
Plaintext

;; Swift optionals over typed values: T?, ??, !, a test's as, and chaining through a field and a function held in a field.
struct Engine
power: i32
boost: CFn(i32) -> i32
struct Car
name: str
engine: Engine?
spare: i32?
fn twice(x: i32) -> i32 = x * 2
fn find(xs: [2 i32?], i: i32) -> i32?
if i < length(xs) then xs[i] else None
;; Counts the defaults evaluated, to show ?? evaluates its right side only
;; when the left holds nothing.
let calls = 0
fn fallback(v: i32) -> i32
calls += 1
v
fn describe(o: i32?) -> i32
if o? as g
g + 100
elif find([None, Some(5)], 1)? as h
h
else
0
fn main()
let a: i32? = Some(3)
let n: i32? = None
println(a ?? 7, n ?? 7)
;; A chain of defaults is read from the right; an Option default keeps it
;; an Option.
println(n ?? n ?? 9)
let still: i32? = n ?? a
println(still!)
;; Short-circuit: fallback runs once, for n.
println(a ?? fallback(1), n ?? fallback(2), calls)
;; Above the comparisons, below arithmetic.
println(n ?? 1 + 1 == 2)
println(a!)
println(describe(Some(1)), describe(None))
let cs: [Car] = [Car{.name "a" .engine Some(Engine{.power 90 .boost twice}) .spare Some(1)},
Car{.name "b" .engine None .spare None}]
for i in range(2)
let c = cs[i]
let p = c.engine?.power
let b = c.engine?.boost(21)
println(c.name, p ?? -1, b ?? -1)
;; Flat: a field that is itself an Option is not wrapped again.
let s: i32? = Some(c)?.spare
println(s ?? -1)
let xs = [Some(4), None]
println(xs[0]!, xs[1] ?? 0)
;; Nested types.
let v: Vec(i32?) = vec-new(i32?)
push(v, Some(1))
push(v, None)
println(length(v), v[0] ?? 0, v[1] ?? 0)