I have provided some lazy power functions to show how you can reuse lazy-seq from a function.
Each time you call my-simple-lazy-power with two numbers, it creates a lazy seq with powers of a certain number x and returns the nth element. Using this version is very expensive, because for each function call exactly one lazy seq is created. This is probably why the reference mine-lazy power is so slow. Since lazy-seqs caches its results, you probably want to reuse them. This is what my-lazy-power does: it creates lazy-seq for the number x and wraps around it a function that takes n as an argument. You can reuse the latter function to access cached results. (The function maintains a link to lazy-seq as long as the function exists, because it is "closed" to lazy-seq. That's why they call it closing.)
Another common way to cache function results is to use a memoized version of the function. Basically, memoize remembers the result for the arguments you pass, so the next time you pass the same arguments, it will return the result from the cache. See examples below. For comparison, I also timed your versions and their memoized versions.
(defn my-simple-lazy-power [xn] (let [my-lazy-list ((fn my-lazy [y] (lazy-cat [y] (map #(* % x) (my-lazy y)))) x)] (nth my-lazy-list n))) (defn my-lazy-power [x] (let [my-lazy-list ((fn my-lazy [y] (lazy-cat [y] (map #(* % x) (my-lazy y)))) x)] (fn [n] (nth my-lazy-list n)))) (defn rec-power [an] (let [multiply (fn [x factor i] (if (zero? i) x (recur (* x factor) factor (dec i))))] (multiply aa (dec n)))) (defn lazy-power [an] (letfn [(multiply [a factor] (lazy-seq (cons a (multiply (* a factor) factor))))] (nth (multiply aa) (dec n)))) (def mem-my-simple-power (memoize my-simple-lazy-power)) (def mem-my-power (memoize my-lazy-power)) (def mem-rec-power (memoize rec-power)) (def mem-laz-power (memoize lazy-power)) (time (dotimes [_ 50] (my-simple-lazy-power 2 512))) "Elapsed time: 7138.346976 msecs" nil (time (let [my-pow-2 (my-lazy-power 2)] (dotimes [_ 10000] (my-pow-2 512)))) "Elapsed time: 854.717301 msecs" nil (time (dotimes [_ 10000] (rec-power 2 512))) "Elapsed time: 2726.559879 msecs" nil (time (dotimes [_ 10000] (mem-rec-power 2 512))) "Elapsed time: 4.775677 msecs" nil (time (dotimes [_ 10000] (lazy-power 2 512))) "Elapsed time: 3617.100209 msecs" nil (time (dotimes [_ 10000] (mem-laz-power 2 512))) "Elapsed time: 4.95887 msecs" nil
PS: I had to write fn around the lazy-seq definition in my versions because let doesn't support recursive definitions, but fn does.
PS2: sorry for the indent, copying the paste from Emacs doesn't seem to save it ...
source share