View source on GitHub | See Demo | Toggle Types language heron:std:0.1; module heron:std.array:0.1 { function unit(x) = [x]; (Array<'a> ('a -> 'b) -> Array<'b>)function map(xs, f) = array(xs.count, i => f(xs[i])); (Array<'a> ('a Int -> 'b) -> Array<'b>)function mapWithIndex(xs, f) = array(xs.count, i => f(xs[i], i)); (Array<'a> (Int -> 'b) -> Array<'b>)function mapIndex(xs, f) = array(xs.count, f); ('a 'a -> 'a)function min(x, y) = x <= y ? x : y; ('a 'a -> 'a)function max(x, y) = x >= y ? x : y; (Array<'a> Array<'a> -> Array<'a>)function shorter(xs, ys) = xs.count <= ys.count ? xs : ys; (Array<'a> Array<'a> -> Array<'a>)function longer(xs, ys) = xs.count >= ys.count ? xs : ys; (Array<'a> -> Bool)function empty(xs) = xs.count == 0; (Array<'a> Array<Int> -> Array<'a>)function selectByIndex(xs, indices) = indices.map(i => xs.at(i)); (Array<'a> -> Array<Int>)function indices(xs) = 0 .. xs.count; (Array<'a> Array<'b> ('a 'b -> 'c) -> Array<'c>)function zip(xs, ys, f) = xs.count <= ys.count ? xs.mapWithIndex((x, i) => f(x, ys[i])) : ys.mapWithIndex((y, i) => f(xs[i], y)); (Array<'a> ('a -> Bool) -> Bool)function all(xs, p) = xs.reduce(true, (prev, x) => prev && p(x)); (Array<'a> ('a -> Bool) -> Bool)function any(xs, p) = xs.reduce(false, (prev, x) => prev || p(x)); //function count(xs, p) // = xs.reduce(0, (prev, x) => p(x) ? prev + 1 : prev); (Array<'a> Array<'b> -> Bool)function eq(xs, ys) = xs.count == ys.count; (Array<'a> ('a -> Bool) -> Array<'a>)function filter(xs, p) { var ys = xs.mutable; var i = 0; for (var x in xs) if (p(x)) ys[i++] = x; return ys.immutable.take(i); } ('a Int -> Array<'a>)function repeat(x, n) = (0 .. n).map(i => x); (Array<'a> ('a 'a -> 'a) -> Array<'a>)function prefixScan(xs, op) { if (xs.empty) return xs; var ys = xs[0].repeat(xs.count).mutable; for (var i in 1 .. ys.count) ys[i] = op(xs[i], ys[i-1]); return ys.immutable; } (Array<'a> -> Array<'a>)function adjacentDifferences(xs) = xs.indices.map(i => i > 0 ? xs[i] - xs[i-1] : xs[i]); (Array<'a> Int Int -> Array<'a>)function slice(xs, from, to) = (from .. to).map(i => xs.at(i)); (Array<'a> Int -> Array<'a>)function stride(xs, n) = (0 .. xs.count / n).map(i => xs[i * n]); (Array<'a> Int Int -> Array<'a>)function stride(xs, from, n) = (0 .. xs.count / n).map(i => xs[from + i * n]); (Array<'a> Int -> Array<Array<'a>>)function strides(xs, n) = (0 .. n).map(i => xs.stride(i, n)); (Array<'a> Int -> Array<Array<'a>>)function slices(xs, n) = (0 .. n).map(i => xs.slice(i * n, (i+1) * n)); (Array<'a> Int -> Array<'a>)function take(xs, n) = xs.slice(0, n); (Array<'a> Int Int -> Array<'a>)function take(xs, i, n) = xs.skip(i).take(n); (Array<'a> Int -> Array<'a>)function skip(xs, n) = xs.slice(n, xs.count - n); (Array<'a> Int -> Array<'a>)function drop(xs, n) = xs.take(xs.count - n); (Array<'a> Int -> Array<'a>)function last(xs, n) = xs.skip(xs.count-n); (Array<'a> 'b -> Array<'a>)function reverse(xs, n) = xs.indices.map(i => xs[xs.count-1-i]); (Int (Int -> 'a) -> Array<'a>)function gen(cnt, f) = (0 .. cnt).map(f); (Array<'a> Array<'a> -> Array<'a>)function concat(xs, ys) = gen(xs.count + ys.count, i => i < xs.count ? xs[i] : ys[i - xs.count]); (Array<'a> Int Int -> Array<'a>)function cut(xs, from, n) = gen(xs.count - n, i => i < from ? xs[i] : xs[i + n]); (Array<'a> Int Array<'a> -> Array<'a>)function splice(xs, from, ys) = xs.take(from).concat(ys).concat(xs.skip(from)); (Array<Float> -> Float)function sum(xs) = xs.reduce(0.0, op+); (Array<Float> -> Float)function product(xs) = xs.reduce(1.0, op*); (Array<Float> -> Float)function average(xs) = xs.sum / xs.count.float; (Array<'a> -> 'a)function min(xs) = xs.reduce(xs[0], min); (Array<'a> -> 'a)function max(xs) = xs.reduce(xs[0], max); (ArrayBuilder<'a> Int Int -> ArrayBuilder<'a>)function swapElements(xs, i, j) { var tmp = xs[i]; xs[i] = xs[j]; xs[j] = tmp; return xs; } (Array<'a> Int Int -> Int)function partition(a, lo, hi) { var p = a[lo]; var i = lo - 1; var j = hi + 1; while (true) { do { i++; } while (a[i] < p); do { j--; } while (a[j] > p); if (i >= j) return j; swapElements(a, i, j); } } (Array<'a> Int Int -> Array<'a>)function qsort(a, lo, hi) { if (lo < hi) { var p = partition(a, lo, hi); qsort(a, lo, p); qsort(a, p+1, hi); } return a; } (Array<'a> -> Array<'a>)function sort(xs) = xs.mutable.qsort(0, xs.count-1).immutable; (Array<Int> -> Int)function median(xs) { var ys = xs.sort; return (ys.count - 1) % 2 == 0 ? ys[(ys.count - 1) / 2] : ys[(ys.count - 2) / 2] + ys[ys.count / 2] / 2; } (Array<'a> Int -> Bool)function inRange(xs, n) = n >= 0 && n < xs.count; (Array<'a> -> 'a)function last(xs) = xs[xs.count - 1]; (Array<'a> -> 'a)function first(xs) = xs[0]; (Array<'a> -> Array<'a>)function tail(xs) = xs.skip(1); (Array<'a> 'b ('b 'a -> 'b) -> 'b)function reduce(xs, acc, f) { for (var x in xs) acc = f(acc, x); return acc; } (Array<Array<'a>> -> Array<'a>)function flatten(xs) = xs.reduce([], concat); (Array<'a> ('a -> Array<'b>) -> Array<'b>)function flatMap(xs, f) = xs.map(f).flatten; // TODO: rewrite using flatMap, but that is slow for now. I will need to write an optimizer (Array<'a> Array<'b> ('a 'b -> 'c) -> Array<'c>)function cartesianProduct(xs, ys, f) { var r = [].mutable; for (var x in xs) for (var y in ys) r.push(f(x, y)); return r.immutable; } (Array<'a> 'b -> Array<'b>)function setAll(xs, x) = xs.map(_ => x); }