diff --git a/CHANGELOG.md b/CHANGELOG.md index a3dccb50..6aea9e77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to this project will be documented in this file. ## Unreleased +- Add `reduce2`, `accumulate`, and `accumulate2`. - Add lockfiles to `jpm` via `jpm make-lockfile` and `jpm load-lockfile`. - Add `os/realpath` (Not supported on windows). - Add `os/chmod`. diff --git a/auxbin/jpm b/auxbin/jpm index 7be76d58..1dcdb6bb 100755 --- a/auxbin/jpm +++ b/auxbin/jpm @@ -686,8 +686,8 @@ int main(int argc, const char **argv) { (def mdir (find-manifest-dir)) (each man (os/dir mdir) (def package (parse (slurp (string mdir sep man)))) - (if (or (not (package :repo)) (not (package :sha))) - (print "Cannot add local package " man " to lockfile, skipping...") + (if (or (not (dictionary? package)) (not (package :repo)) (not (package :sha))) + (print "Cannot add local or malformed package " mdir sep man " to lockfile, skipping...") (array/push packages package))) # Put in correct order, such that a package is preceded by all of its dependencies (def ordered-packages @[]) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 3334b1f8..44203722 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -699,6 +699,43 @@ (each x ind (set res (f res x))) res) +(defn reduce2 + "The 2 argument version of reduce that does not take an initialization value. + Instead the first element of the array is used for initialization." + [f ind] + (var k (next ind)) + (var res (in ind k)) + (set k (next ind k)) + (while (not= nil k) + (set res (f res (in ind k))) + (set k (next ind k))) + res) + +(defn accumulate + "Similar to reduce, but accumulates intermediate values into an array. + The last element in the array is what would be the return value from reduce. + The init value is not added to the array. + Returns a new array." + [f init ind] + (var res init) + (def ret (array/new (length ind))) + (each x ind (array/push ret (set res (f res x)))) + ret) + +(defn accumulate2 + "The 2 argument version of accumulate that does not take an initialization value." + [f ind] + (var k (next ind)) + (def ret (array/new (length ind))) + (var res (in ind k)) + (array/push ret res) + (set k (next ind k)) + (while (not= nil k) + (set res (f res (in ind k))) + (array/push ret res) + (set k (next ind k))) + ret) + (defn map "Map a function over every element in an indexed data structure and return an array of the results." diff --git a/test/suite8.janet b/test/suite8.janet index 580cd3be..b20fb7e6 100644 --- a/test/suite8.janet +++ b/test/suite8.janet @@ -181,4 +181,14 @@ (def c (unmarshal (marshal b))) (assert (= 2 (c 1)) "marshal-on-stack-closure 1")) +# Reduce2 + +(assert (= (reduce + 0 (range 1 10)) (reduce2 + (range 10))) "reduce2 1") +(assert (= (reduce * 1 (range 2 10)) (reduce2 * (range 1 10))) "reduce2") + +# Accumulate + +(assert (deep= (accumulate + 0 (range 5)) @[0 1 3 6 10]) "accumulate 1") +(assert (deep= (accumulate2 + (range 5)) @[0 1 3 6 10]) "accumulate2 1") + (end-suite)