Heh. Thought of an improvement: (defn make-atom-setter-fn-expr [names skip?] (let [arglist-1 (map #(gensym %) names) arglist (vec (if skip? arglist-1 (cons (gensym 'item) arglist-1)))] `(~(if skip? 'skip-item 'next-item) ~arglist ~@(map (fn [nm gs] (list 'reset! nm gs)) names arglist-1) ~(if skip? :skip [(first arglist)]))))
(defmacro super-lazy-seq [bindings & body] (let [binds (bindings-to-atoms bindings) code (with-derefs (set (take-nth 2 bindings)) body)] `(let ~binds (letfn [~(make-atom-setter-fn-expr (take-nth 2 bindings) false) ~(make-atom-setter-fn-expr (take-nth 2 bindings) true) (helper-fn# [] (lazy-seq (loop [] (let [item# (do ~...@code)] (if item# (if-not (= item# :skip) (cons (first item#) (helper-fn#)) (recur)))))))] (helper-fn#))))) With this, your loop body can use (skip-item val1 val2) to go back to the start of the loop with new bindings but without generating an item, as well as (next-item item val1 val2) to generate an item. And items can still be anything, including false, nil, or the :skip keyword that is used internally by the above code, due to the vector- wrap. With the modified super-lazy-seq my file-lines-seq became a heck of a lot shorter. It is 23 lines. It was twice that without super-lazy-seq and somewhere in between with the old super-lazy-seq. It benefits from skip-item because a file might have zero lines, and we don't want empty files polluting the seq with nils. Between files-and-dirs and file-lines-seq I think I have saved as many lines of code as are in the macro+helper fns, so those are at break- even. As soon as I have another use for super-lazy-seq it starts actually paying off. Or as soon as anyone else does. As before, the code I've posted here is public domain. Anyone can use it for anything without asking permission. I'm not much of a believer in copyright, certainly not for basic and commonly-wanted snippets of program code. :) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---