diff --git a/lib/std/core/list.kk b/lib/std/core/list.kk
index 27a1c843f..2ff500037 100644
--- a/lib/std/core/list.kk
+++ b/lib/std/core/list.kk
@@ -328,9 +328,13 @@ pub fun filter( xs : list, pred : a -> e bool ) : e list
// Remove those elements of a list that satisfy the given predicate `pred`.
// For example: `remove([1,2,3],odd?) == [2]`
-pub fun remove( xs : list, pred : a -> e bool ) : e list
+pub fun pred/remove( xs : list, pred : a -> e bool ) : e list
xs.filter( fn(x) !pred(x) )
+// Remove those elements of a list that are equal to `value`.
+pub fun eq/remove( xs : list, value : a, ?(==) : (a,a) -> e bool ) : e list
+ xs.filter( fn(x) !(x==value) )
+
// Partition a list in two lists where the first list contains
// those elements that satisfy the given predicate `pred`.
// For example: `partition([1,2,3],odd?) == ([1,3],[2])`
@@ -353,6 +357,12 @@ pub fun filter-map( xs : list, pred : a -> e maybe ) : e list
Nothing -> xx.filter-map(pred)
Just(y) -> Cons(y,xx.filter-map(pred))
+// Does the list contain the given value?
+pub fun contains( xs : list, value : a, ?(==) : (a,a) -> e bool ) : e bool
+ match xs
+ Cons(x,xx) -> if x==value then True else xx.contains(value)
+ Nil -> False
+
// Find the first element satisfying some predicate
pub fun find( xs : list, pred : a -> e bool ) : e maybe
xs.foreach-while fn(x)
@@ -363,10 +373,14 @@ pub fun find-maybe( xs : list, pred : a -> e maybe ) : e maybe
xs.foreach-while(pred)
// Lookup the first element satisfying some predicate
-pub fun lookup( xs : list<(a,b)>, pred : a -> e bool ) : e maybe
- xs.foreach-while fn(kv)
- if pred(kv.fst) then Just(kv.snd) else Nothing
+pub fun pred/lookup( xs : list<(a,b)>, pred : a -> e bool ) : e maybe
+ xs.foreach-while fn((fst, snd))
+ if pred(fst) then Just(snd) else Nothing
+// Lookup the value for a given key
+pub fun eq/lookup( xs : list<(a,b)>, key : a, ?(==) : (a,a) -> e bool ) : e maybe
+ xs.foreach-while fn((fst, snd))
+ if fst==key then Just(snd) else Nothing
// Convert a `:maybe` type to a list type.
pub fun maybe/list( m : maybe ) : list
@@ -381,9 +395,17 @@ fun index-of-acc( xs : list, pred : a -> e bool, idx : int ) : e int
// Returns the index of the first element where `pred` holds, or `-1` if no such element exists.
-pub fun index-of( xs : list, pred : a -> e bool ) : e int
+pub fun pred/index-of( xs : list, pred : a -> e bool ) : e int
index-of-acc( xs, pred, 0 )
+// Returns the index of the first element equal to `value` or `-1` if no such element exists.
+pub fun eq/index-of( xs : list, value : a, ?(==) : (a,a) -> e bool ) : e maybe
+ fun recur( ys, idx )
+ match ys
+ Cons(y,yy) -> if y==value then Just(idx) else recur(yy,idx+1)
+ Nil -> Nothing
+ recur(xs,0)
+
// Invoke `action` for each element of a list
pub fun foreach( xs : list, action : (a) -> e () ) : e ()
match xs
diff --git a/lib/std/core/show.kk b/lib/std/core/show.kk
index 3356d1cc5..989e80ea0 100644
--- a/lib/std/core/show.kk
+++ b/lib/std/core/show.kk
@@ -16,6 +16,7 @@ import std/core/char
import std/core/string
import std/core/sslice
import std/core/list
+import std/core/vector
// ----------------------------------------------------------------------------
@@ -69,4 +70,6 @@ pub noinline fun string/show( s : string ) : string
pub fun sslice/show( s : sslice ) : string
s.string.show
-
+// Show a vector as a string
+pub fun vector/show( v : vector, ?show: a -> e string ) : e string
+ "[" ++ v.map(show).join(",") ++ "]"
\ No newline at end of file
diff --git a/lib/std/core/vector.kk b/lib/std/core/vector.kk
index d68e44c72..fa960d888 100644
--- a/lib/std/core/vector.kk
+++ b/lib/std/core/vector.kk
@@ -22,6 +22,8 @@ extern import
// ----------------------------------------------------------------------------
// Vectors
// ----------------------------------------------------------------------------
+// TODO: Consider in-place updates when reference count is 1 throughout!
+// Also, start benchmarking
// Return the element at position `index` in vector `v` without bounds check!
inline extern unsafe-idx( ^v : vector, index : ssize_t ) : total a
@@ -132,6 +134,160 @@ pub fun map( v : vector, f : a -> e b ) : e vector
unsafe-assign(w,i,f(x))
w
+// Apply a function `f` to each element in a vector `v`
+pub fun map-indexed(v : vector, f: (int, a) -> e b): e vector
+ val w = unsafe-vector(v.length.ssize_t)
+ v.foreach-indexedz fn(i,x)
+ unsafe-assign(w,i,f(i.int, x))
+ w
+
+// Fold over a vector from the start, accumulating a result
+pub fun foldl( v : vector, initial : b, f : (b,a) -> e b ) : e b
+ val length = v.lengthz
+ fun loop(i, acc)
+ if i < length then
+ val acc2 = f(acc, v.unsafe-idx(i))
+ loop(i.incr.pretend-decreasing, acc2)
+ else acc
+ loop(0.ssize_t, initial)
+
+// Fold over a vector from the end, accumulating a result
+pub fun foldr( v : vector, initial : b, f : (a,b) -> e b ) : e b
+ val length = v.lengthz
+ fun loop(i, acc)
+ if i >= 0.ssize_t then
+ val acc2 = f(v.unsafe-idx(i), acc)
+ loop(i.decr.pretend-decreasing, acc2)
+ else acc
+ loop(length.decr, initial)
+
+// Zip two vectors into a vector of pairs.
+pub fun zip( v1 : vector, v2 : vector ) : vector<(a,b)>
+ val l1 = v1.lengthz
+ val l2 = v2.lengthz
+ val l = if l1 <= l2 then l1 else l2
+ val w = unsafe-vector(l)
+ forz( l ) fn(i)
+ unsafe-assign(w,i,(v1.unsafe-idx(i), v2.unsafe-idx(i)))
+ w
+
+// Zip two vectors using a function `f` to combine elements.
+pub fun zip-with( v1 : vector, v2 : vector, f : (a,b) -> c ) : vector
+ val l1 = v1.lengthz
+ val l2 = v2.lengthz
+ val l = if l1 <= l2 then l1 else l2
+ val w = unsafe-vector(l)
+ forz( l ) fn(i)
+ unsafe-assign(w,i,f(v1.unsafe-idx(i), v2.unsafe-idx(i)))
+ w
+
+// Zip two vectors using a function `f` to combine elements.
+// The current index is passed as the first argument to `f`.
+pub fun zip-with-indexed( v1 : vector, v2 : vector, f : (int,a,b) -> c ) : vector
+ val l1 = v1.lengthz
+ val l2 = v2.lengthz
+ val l = if l1 <= l2 then l1 else l2
+ val w = unsafe-vector(l)
+ forz( l ) fn(i)
+ unsafe-assign(w,i,f(i.int, v1.unsafe-idx(i), v2.unsafe-idx(i)))
+ w
+
+// Equality of vectors
+pub fun vector/(==)(v1 : vector, v2: vector, ?(==): (a, a) -> e bool): e bool
+ val l = v1.lengthz
+ if l != v2.lengthz then
+ False
+ else
+ val eq = for-whilez(l) fn(i)
+ // Found a difference can end iteration and return False immediately
+ if !(v1.unsafe-idx(i) == v2.unsafe-idx(i)) then Just(())
+ else Nothing
+ match eq
+ Just() -> False
+ Nothing -> True
+
+// In-equality of vectors (specialized for performance)
+pub fun vector/(!=)(v1 : vector, v2: vector, ?(==): (a, a) -> e bool): e bool
+ val l = v1.lengthz
+ if l != v2.lengthz then
+ True
+ else
+ val eq = for-whilez(l) fn(i)
+ // Found a difference can end iteration and return True immediately
+ if !(v1.unsafe-idx(i) == v2.unsafe-idx(i)) then Just(())
+ else Nothing
+ match eq
+ Just() -> True
+ Nothing -> False
+
+// Take the first `n` elements from a vector.
+pub fun take( v : vector, ^n : int ) : vector
+ val len = v.lengthz
+ val tn = if n.ssize_t < len then n.ssize_t else len
+ val w = unsafe-vector(tn)
+ forz( tn ) fn(i)
+ unsafe-assign(w,i,v.unsafe-idx(i))
+ w
+
+// Take the first `n` elements from a vector as a list.
+pub fun take-list( v : vector, ^n : int ) : list
+ val len = v.lengthz
+ val tn = if n.ssize_t < len then n.ssize_t else len
+ fun loop(i : ssize_t, acc : ctx>) : list<_>
+ if i < tn then
+ loop(i.incr.pretend-decreasing, acc ++ ctx Cons(v.unsafe-idx(i), hole))
+ else
+ acc ++. Nil
+ loop(0.ssize_t, ctx hole)
+
+// Drop the first `n` elements from a vector.
+pub fun drop( v : vector, ^n : int ) : vector
+ val len = v.lengthz
+ val ns = n.ssize_t
+ val dn = if ns < 0.ssize_t then 0.ssize_t elif ns < len then ns else len
+ val newlen = len - dn
+ val w = unsafe-vector(newlen)
+ forz( newlen ) fn(i)
+ unsafe-assign(w,i,v.unsafe-idx(i + dn))
+ w
+
+// Take a slice from the vector from `start` (inclusive) to `end` (exclusive).
+pub fun slice( v : vector, ^start : int, ^end : int ) : vector
+ val len = v.lengthz
+ val starts = start.ssize_t
+ val ends = end.ssize_t
+ val s = if starts < 0.ssize_t then 0.ssize_t elif starts > len then len else starts
+ val e = if ends < s then s elif ends > len then len else ends
+ val slen = e - s
+ val w = unsafe-vector(slen)
+ forz( slen ) fn(i)
+ unsafe-assign(w,i,v.unsafe-idx(i + s))
+ w
+
+// Reverses a vector
+pub fun reverse( v : vector ) : vector
+ val len = v.lengthz
+ val w = unsafe-vector(len)
+ forz( len ) fn(i)
+ unsafe-assign(w,i,v.unsafe-idx(len - i - 1.ssize_t))
+ w
+
+// Append two vectors
+pub fun append( v1 : vector, v2 : vector ) : vector
+ val l1 = v1.lengthz
+ val l2 = v2.lengthz
+ val l = l1 + l2
+ val w = unsafe-vector(l)
+ forz( l1 ) fn(i)
+ unsafe-assign(w,i,v1.unsafe-idx(i))
+ forz( l2 ) fn(i)
+ unsafe-assign(w,i + l1,v2.unsafe-idx(i))
+ w
+
+// Append two vectors
+pub fun vector/(++)( v1 : vector, v2 : vector ): vector
+ append(v1,v2)
+
// Convert a vector to a list.
pub fun list( v : vector ) : list
v.vlist
@@ -177,6 +333,12 @@ fun for-whilez( n : ssize_t, action : (ssize_t) -> e maybe ) : e maybe
// Minimal set of operations that we need in `std/core`.
+inline fip extern ssize_t/(==) : (ssize_t,ssize_t) -> bool
+ inline "(#1 == #2)"
+
+inline fip extern ssize_t/(!=) : (ssize_t,ssize_t) -> bool
+ inline "(#1 != #2)"
+
inline fip extern ssize_t/(<=) : (ssize_t,ssize_t) -> bool
inline "(#1 <= #2)"
@@ -186,6 +348,9 @@ inline fip extern ssize_t/(>=) : (ssize_t,ssize_t) -> bool
inline fip extern ssize_t/(<) : (ssize_t,ssize_t) -> bool
inline "(#1 < #2)"
+inline fip extern ssize_t/(>) : (ssize_t,ssize_t) -> bool
+ inline "(#1 > #2)"
+
inline fip extern ssize_t/(+) : (ssize_t,ssize_t) -> ssize_t
inline "(#1 + #2)"
js inline "((#1 + #2)|0)"