I have written a function (listed below) which returns a function that returns n items from an infiniate set as defined in the comments.
; Returns a function which in turn returns a vector of 'n' items, with init-val being the 'middle' value,
; Values to the 'right' of init-val being 'step' added to the (previously) last value, and items 'left' of
; 'init-val' being 'step' subtracted from the (previously) first value in the list.
(defn range-right-left [init-val step]
(fn [n] ; produce a vector containing 'n' items
(loop [Vector (cond (zero? n) []
(pos? n) [init-val]
:else nil)]
(if (or (= (count Vector) n) (nil? Vector)) Vector ; base case(s)
(recur
(if (odd? (count Vector))
(conj Vector (+ (last Vector) step)) ; add 'step' to the last element of the vector and place it on the back of the vector
(vec (cons (- (first Vector) step) Vector)))))))) ;else if Vector contains an even number of items, subtract step from the first item in the vector and place it on front of the resulting collection (converting to vector)
To clarify the behavior of the function, I am including the code for the tests (which all passed).
(deftest range-right-left-test
(is (= nil ((range-right-left 7 3) -1)))
(is (= [] ((range-right-left 7 3) 0)))
(is (= [7] ((range-right-left 7 3) 1)))
(is (= [7 10] ((range-right-left 7 3) 2)))
(is (= [4 7 10] ((range-right-left 7 3) 3)))
(is (= [4 7 10 13] ((range-right-left 7 3) 4)))
(is (= [1 4 7 10 13] ((range-right-left 7 3) 5))))
What I would really like, though, is for 'range-right-left' to return a lazy sequence instead of a function. In other words, instead of doing this:
((range-right-left 7 3) 3)
I would like to be able to do:
(take 3 (range-right-left 7 3))
It seems to be the default behavior for lazy sequences to strictly grow from left to right. I have tried to develop a lazy seq that can grow in both directions, to no avail. I would very much appreciate suggestions to do such.