Skip to content

pipe

Fused pipelines: lists.fuse! runs map and filter stages over a list as one loop, with no list in between. Written with lists.map and lists.filter, the same pipeline builds a new list at every stage; fused, it runs about three times as fast natively, as fast as the loop written out by hand.

fuse! is a macro in lib/lists.jh, written in jihoo. It runs on the VM while compiling: it takes the stages as code, any number of them, reads each with meta.node to see map(f) or filter(g), asks type_of what type the last stage gives, and puts it all together into one for loop in a block expression. See the design in docs/internals/code-as-data.md.

Terminal window
jihoo run examples/pipe.jh
examples/pipe.jh
import lists
fn main() {
let xs: [i64] = []
for i in 0..1000 {
push(xs, i % 100)
}
let k = 7
// With a list for `map` and another for `filter`.
let ys = lists.map(xs, fn(x) -> i64 { return x * 3 + k })
let zs = lists.filter(ys, fn(x) { return x % 2 == 0 })
print(lists.fold(zs, 0, fn(a, x) { return a + x }))
// Fused: one loop, no list in between. Prints the same.
let s = lists.fuse!(xs,
map(fn(x: i64) -> i64 { return x * 3 + k }),
filter(fn(x: i64) -> bool { return x % 2 == 0 }),
sum())
print(s)
// Any number type: here the stages end in `f64`.
print(lists.fuse!(xs,
filter(fn(x: i64) -> bool { return x < 10 }),
map(fn(x: i64) -> f64 { return x as f64 / 4.0 })))
// Other ends: how many are left, or a list of them.
print(lists.fuse!(xs, filter(fn(x: i64) -> bool { return x > 90 }), count()))
let big = lists.fuse!(xs,
filter(fn(x: i64) -> bool { return x > 97 }),
map(fn(x: i64) -> str { return to_str(x) + "!" }),
collect())
print(len(big))
print(big[0])
}

View on GitHub