Add accumulate(2) and reduce2

These functions are variations on reduce and can be quite useful.
Improve error message for jpm as well.
This commit is contained in:
Calvin Rose 2020-03-26 21:35:11 -05:00
parent a3a45511e5
commit 3eb0927a2b
4 changed files with 50 additions and 2 deletions

View File

@ -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`.

View File

@ -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 @[])

View File

@ -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."

View File

@ -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)