diff --git a/jolt-core/clojure/core/00-syntax.clj b/jolt-core/clojure/core/00-syntax.clj index 0303c27..b2bebfd 100644 --- a/jolt-core/clojure/core/00-syntax.clj +++ b/jolt-core/clojure/core/00-syntax.clj @@ -95,3 +95,9 @@ (first cls) `(if ~(mk-test (first cls)) ~(nth cls 1) ~(build (drop 2 cls))))))] `(let* [~g ~expr] ~(build clauses)))) + +;; doseq runs body for side effects across the bindings, returning nil. Same +;; shortcut as the prior Janet macro: realize a `for` comprehension with count +;; (for handles :when/:let/:while and multiple bindings). +(defmacro doseq [bindings & body] + `(do (count (for ~bindings (do ~@body nil))) nil)) diff --git a/src/jolt/core.janet b/src/jolt/core.janet index 1bd8041..91e1ef3 100644 --- a/src/jolt/core.janet +++ b/src/jolt/core.janet @@ -2364,13 +2364,6 @@ # doseq — like `for` but eager and returns nil. Reuse `for`, force realization # with `count`, discard the result. -(defn core-doseq [bindings & body] - (def for-body @[{:jolt/type :symbol :ns nil :name "do"} ;body nil]) - @[{:jolt/type :symbol :ns nil :name "do"} - @[{:jolt/type :symbol :ns nil :name "count"} - @[{:jolt/type :symbol :ns nil :name "for"} bindings for-body]] - nil]) - # assert — (assert x) / (assert x message). Throws when x is falsy. # resolve stub — returns nil (symbols not found in Jolt's clojure.core) @@ -3174,7 +3167,6 @@ "pop" core-pop "trampoline" core-trampoline "format" core-format - "doseq" core-doseq "first" core-first "rest" core-rest "next" core-next @@ -3562,7 +3554,7 @@ (defn core-macro-names "Set of core binding names that are macros." [] - @{"for" true "when-let" true "defn" true "defn-" true "fn" true "let" true "loop" true "defrecord" true "defprotocol" true "extend-type" true "extend-protocol" true "extend" true "reify" true "proxy" true "definterface" true "lazy-seq" true "lazy-cat" true "doseq" true}) + @{"for" true "when-let" true "defn" true "defn-" true "fn" true "let" true "loop" true "defrecord" true "defprotocol" true "extend-type" true "extend-protocol" true "extend" true "reify" true "proxy" true "definterface" true "lazy-seq" true "lazy-cat" true}) (def init-core! (fn [& args] diff --git a/test/spec/control-flow-spec.janet b/test/spec/control-flow-spec.janet index ee12855..eab82a6 100644 --- a/test/spec/control-flow-spec.janet +++ b/test/spec/control-flow-spec.janet @@ -69,7 +69,11 @@ ["for :while" "[0 1 2]" "(for [x (range 10) :while (< x 3)] x)"] ["for :let" "[0 1 4]" "(for [x (range 3) :let [sq (* x x)]] sq)"] ["doseq side-effect" "6" "(let [a (atom 0)] (doseq [x [1 2 3]] (swap! a (fn [v] (+ v x)))) @a)"] - ["doseq nested" "4" "(let [c (atom 0)] (doseq [x [1 2] y [10 20]] (swap! c inc)) @c)"]) + ["doseq nested" "4" "(let [c (atom 0)] (doseq [x [1 2] y [10 20]] (swap! c inc)) @c)"] + ["doseq :when" "[1 3]" "(let [a (atom [])] (doseq [x [1 2 3] :when (odd? x)] (swap! a conj x)) @a)"] + ["doseq :while" "6" "(let [a (atom 0)] (doseq [x (range 10) :while (< x 4)] (swap! a + x)) @a)"] + ["doseq :let" "[0 1 4]" "(let [a (atom [])] (doseq [x (range 3) :let [sq (* x x)]] (swap! a conj sq)) @a)"] + ["doseq returns nil" "nil" "(doseq [x [1 2 3]] x)"]) (defspec "control / threading" ["->" "6" "(-> 1 inc (+ 4))"]