diff --git a/NEWS.rst b/NEWS.rst index a20bd14..71da3c9 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -36,6 +36,8 @@ Bug Fixes * Fixed crashes from inaccessible history files. * The unit tests no longer unintentionally import the internal Python module "test". This allows them to pass when run inside the "slim" Python Docker images. +* `ap-reduce` now accepts any iterable. +* `ap-reduce` now evaluates its arguments only once. Misc. Improvements ------------------------------ diff --git a/hy/extra/anaphoric.hy b/hy/extra/anaphoric.hy index 602d9ef..d53e9fc 100644 --- a/hy/extra/anaphoric.hy +++ b/hy/extra/anaphoric.hy @@ -91,12 +91,15 @@ ~n))) -(defmacro ap-reduce [form lst &optional [initial-value None]] +(defmacro! ap-reduce [form o!lst &optional [initial-value None]] "Anaphoric form of reduce, `acc' and `it' can be used for a form" `(do - (setv acc ~(if (none? initial-value) `(get ~lst 0) initial-value)) - (ap-each ~(if (none? initial-value) `(cut ~lst 1) lst) - (setv acc ~form)) + (setv acc ~(if (none? initial-value) + `(do + (setv ~g!lst (iter ~g!lst)) + (next ~g!lst)) + initial-value)) + (ap-each ~g!lst (setv acc ~form)) acc)) diff --git a/tests/native_tests/extra/anaphoric.hy b/tests/native_tests/extra/anaphoric.hy index e88e974..d99779f 100644 --- a/tests/native_tests/extra/anaphoric.hy +++ b/tests/native_tests/extra/anaphoric.hy @@ -64,7 +64,17 @@ (assert (= (ap-reduce (* acc it) [1 2 3] 6) 36)) (assert (= (ap-reduce (+ acc " on " it) ["Hy" "meth"]) "Hy on meth")) - (assert (= (ap-reduce (+ acc it) [] 1) 1))) + (assert (= (ap-reduce (+ acc it) [] 1) 1)) + + ; https://github.com/hylang/hy/issues/1848 + (assert (= (ap-reduce (* acc it) (map inc [1 2 3])) 24)) + (assert (= (ap-reduce (* acc it) (map inc [1 2 3]) 4) 96)) + + (setv expr-evaluated 0) + (assert (= + (ap-reduce (* acc it) (do (+= expr-evaluated 1) [4 5 6]))) + 120) + (assert (= expr-evaluated 1))) (defn test-tag-fn [] ;; test ordering