; A fixed-size ring buffer of samples, generic over the element type, with ; the statistics a sensor log wants: a median, the distinct values, and a ; checksum over the raw bytes. struct Ring items: [$n $t] head: i32 count: i32 struct Reading sensor: u8 value: i32 fn push-ring!(r: Ptr(Ring($n, $t)), x: $t) -> () r.items[r.head] = x r.head = (r.head + 1) % n if r.count < n r.count += 1 ; The oldest sample first. fn nth-oldest(r: Ptr(Ring($n, $t)), i: i32) -> $t let start = if r.count < n then 0 else r.head r.items[(start + i) % n] fn copy-out(r: Ptr(Ring($n, $t))) -> Vec($t) let v = vec-new(t) for i in range(r.count) push(v, nth-oldest(r, i)) v fn median(xs: [$t]) -> Option($t) where is-ordered($t), is-equal($t) if length(xs) == 0 return None sort(xs) Some(xs[length(xs) / 2]) fn distinct(xs: [const $t]) -> Vec($t) where is-equal($t), is-hashable($t) let seen = map-new(t, bool) defer free(seen) let out = vec-new(t) for i in range(length(xs)) if not has-key(seen, xs[i]) put(seen, xs[i], true) push(out, xs[i]) out ; FNV-1a over the bytes of any array of plain values. fn checksum(p: Ptr(u8), size: i64) -> u32 let bytes = slice-from(p, size) let h: u32 = 2166136261 for i in range(length(bytes)) h = bit-xor(h, u32(bytes[i])) h = h * 16777619 h ; Apply f n times, for any element type. fn repeat-apply(f: CFn($t) -> $t, x: $t, n: i32) -> $t let v = x for i in range(n) v = f(v) v fn halve-all(x: $t) -> $t where is-numeric($t) = repeat-apply(fn(a: $t) -> $t => a / 2, x, 3) fn main() -> i32 let r: Ring(5, i32) = zeroed() let samples = [7 3 9 3 12 5 3 8] for :fill i in range(length(samples)) if samples[i] > 10 continue :fill push-ring!(addr(r), samples[i]) let kept = copy-out(addr(r)) defer free(kept) println("kept", slice(kept)) match median(slice(kept)) Some(m) -> println("median", m) None -> println("no samples") let empty: [0 i32] = zeroed() println("median of none", or-else(median(slice(empty)), -1)) let d = distinct(slice(samples)) println("distinct", slice(d)) free(d) let big = filter(slice(samples), fn(x) => x >= 7) println("seven and up", slice(big), "sum", reduce(slice(big), 0, fn(a, b) => a + b)) free(big) let rs = [Reading{.sensor 2, .value 40} Reading{.sensor 1, .value 15} Reading{.sensor 3, .value 22}] sort-by(slice(rs), fn(a, b) => a.value < b.value) for i in range(length(rs)) println("sensor", rs[i].sensor, rs[i].value) let raw: [4 u32] = [1 2 3 4] let p = Ptr(u8)(addr(raw[0])) println("checksum", checksum(p, 16)) println("doubled", repeat-apply(fn(a: i32) -> i32 => a * 2, 1, 10), "halved", halve-all(800.0)) 0