For macro fails sometimes
Opened this issue · 2 comments
The only discernible pattern seems to be that :when
clauses never work. But those aren't the only ones that are failing.
I'm not sure how long it's been this way, but I seem to remember that :when
used to work. My guess is that it was when destructuring was added.
These examples all work:
(def digits [1 2 3])
(for [x1 digits
x2 digits]
(* x1 x2))
(for [x ['a 'b 'c]
y [1 2 3]]
[x y])
(for [x (range 1 6)
:let [y (* x x)
z (* x x x)]]
[x y z])
(for [x (range 6)]
(* x x))
(for [x (range 3) y (range 3)] [x y])
(for [x (range 3) :while (not= x 1) y (range 3)] [x y])
(defn prime? [n]
(not-any? zero? (map #(rem n %) (range 2 n))))
(for [x (range 3 33 2) :while (prime? x)]
x)
(for [x (range 3 17 2) :while (prime? x)
y (range 3 17 2) :while (prime? y)]
[x y])
These do not:
(for [x [0 1 2 3 4 5]
:let [y (* x 3)]
:when (even? y)]
y)
=>
Error: seq: called on non-sequence
(for [[x y] '([:a 1] [:b 2] [:c 0]) :when (= y 0)] x)
=>
Error: Invalid 'for' keyword :b
(for [x (range 3) y (range 3) :when (not= x y)] [x y])
=>
Error: seq: called on non-sequence
(for [x (range 3) y (range 3) :while (not= x y)] [x y])
=>
Error: seq: called on non-sequence
(for [x (range 3) y (range 3) :while (not= x 1)] [x y])
=>
Error: seq: called on non-sequence
(defn prime? [n]
(not-any? zero? (map #(rem n %) (range 2 n))))
(for [x (range 3 33 2) :when (prime? x)]
x)
=>
Error: seq: called on non-sequence
(for [x (range 3 17 2) :when (prime? x)
y (range 3 17 2) :when (prime? y)]
[x y])
(for [x [1 2 3]
y [1 2 3]
:while (<= x y)
z [1 2 3]]
[x y z])
Here is a macroexpansion of a call to for
that fails, followed by one that works:
(let* [G__2561 (defn iter__2562 [s__2563]
(loop [s__2563 s__2563]
(when-let [s__2563 (seq s__2563)]
(let [[x y] (first s__2563)]
(if (= y 0)
(cons x (iter__2562 (rest s__2563)))
(#function[do-mod] (rest s__2563)))))))]
(remove nil?
(G__2561 (quote ([:a 1] [:b 2] [:c 0])))))
(let* [G__2849 (defn iter__2850 [s__2851]
(loop [s__2851 s__2851]
(when-first [x s__2851]
(when (not= x 1)
(let [iterys__2852 (defn iter__2868 [s__2869]
(loop [s__2869 s__2869]
(when-let [s__2869 (seq s__2869)]
(let [y (first s__2869)]
(cons [x y] (iter__2868 (rest s__2869)))))))
fs__2853 (seq (iterys__2852 (range 3)))]
(if fs__2853
(concat fs__2853 (iter__2850 (rest s__2851)))
(#function[do-mod] (rest s__2851))))))))]
(remove nil? (G__2849 (range 3))))
clj-kondo informs me that the loop
expressions are missing recurs. That is because the recur happens in do-mod
.
Come to think of it, the way loop/recur works was also changed significantly. But that's because the old implementation was very much wrong. It used to hold the loop locals in a global variable, and now recur works by constructing a new call to loop
using the new values.
I made it so the error message from seq
prints the object attempted to sequence. They happen to be numbers:
(for [x [0 1 2 3 4 5]
:let [y (* x 3)]
:when (even? y)]
y)
=>
Error: seq: called on non-sequence: 2