I have a function that is supposed to take a lazy seq and return an unrealized lazy seq. Now I want to write a unit test (in test-is btw) to make sure that the result is an unrealized lazy sequence.
-
1How about giving us the code for the function. Throw us a bone. – Kelly S. French Oct 30 '09 at 19:54
-
5Perhaps he's referring to the queue in front of the unemployment office? *snare tom hi-hat* – Jeff Meatball Yang Oct 30 '09 at 21:54
-
2"Unrealized lazy sequence", story of my life. – Brian Carper Oct 30 '09 at 23:00
-
I have a lot of different functions I would like to test with this. I'm really looking for an assert-is-lazy macro for test-is – Arthur Ulfeldt Oct 31 '09 at 19:04
2 Answers
user=> (instance? clojure.lang.LazySeq (map + [1 2 3 4] [1 2 3 4]))
true
If you have a lot of things to test, maybe this would simplify it:
(defmacro is-lazy? [x] `(is (instance? clojure.lang.LazySeq ~x)))
user=> (is-lazy? 1)
FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:7)
expected: (clojure.core/instance? clojure.lang.LazySeq 1)
actual: (not (clojure.core/instance? clojure.lang.LazySeq 1))
false
user=> (is-lazy? (map + [1 2 3 4] [1 2 3 4]))
true
As of Clojure 1.3 there is also the realized?
function: "Returns true if a value has been produced for a promise, delay, future or lazy sequence."

- 10,586
- 3
- 34
- 63
-
Looks like it doesn't work. "iterate" returns a lazy seq, but (instance? clojure.lang.LazySeq (iterate inc 10)) => false – Ruslan Feb 01 '16 at 09:51
-
I'm still learning Clojure, but doesn't it mean that this approach is not universal? So, there might be lots of different implementations of laziness, right? So, looks like the other answer (with checking the side effects) is more universal. But let me know if I'm missing anything here. – Ruslan Feb 03 '16 at 12:06
-
Yes, you are right. There is also now a better way to answer this question; the `realized?` function (added in 1.3) will handle all things pending. Notably (realized? (iterate inc 10)) => true. I speculate that it is valid to call this a lazy sequence, but that the first element must be realized because it is passed as an argument, so there is no way to avoid that. I think that testing the return type meets the goals of the question, and is less intrusive than the alternative. – Timothy Pratley Feb 04 '16 at 06:25
-
What is the point of using a macro here if you can use a function? Wouldn’t `(defn is-lazy [x] (is (instance? clojure.lang.LazySeq x))` work the same way? – bfontaine Sep 13 '16 at 12:07
-
1@bfontaine Yes a function works well. When writing tests you often want the fail result to show you clearly what went wrong. Function arguments are evaluated, so the fail report will print the value that was passed in, not the form that was passed in. Whereas with a macro the original form is preserved unevaluated, so the fail report is a little clearer. For example `(is-lazy? (vec (map inc (range 10))))` as a macro will report `expected: (clojure.core/instance? clojure.lang.LazySeq (vec (map inc (range 10))))` but the function will show `[1 2 3 4 5 6 7 8 9 10]`... just a matter of preference. – Timothy Pratley Sep 13 '16 at 14:32
Use a function with a side effect (say, writing to a ref) as the sequence generator function in your test case. If the side effect never happens, it means the sequence remains unrealized... as soon as the sequence is realized, the function will be called.
First, set it up like this:
(def effect-count (ref 0))
(defn test-fn [x]
(do
(dosync (alter effect-count inc))
x))
Then, run your function. I'll just use map, here:
(def result (map test-fn (range 1 10)))
Test if test-fn ever ran:
(if (= 0 @effect-count)
(println "Test passed!")
(println "Test failed!"))
Since we know map is lazy, it should always work at this point. Now, force evaluation of the sequence:
(dorun result)
And check the value of effect-count again. This time, we DO expect the side effect to have triggered. And, it is so...
user=>@effect-count
9

- 8,440
- 3
- 41
- 54
-
1I'm looking for a way to test any-function not a-function-to-test – Arthur Ulfeldt Dec 09 '09 at 22:43