Hi Everybody,
I just wrote a simple macro to tame the run-away loop-recur infinite
loops. Some of you may find use for it. It only handles loop-recur pairs
not fn-recur combination. It is trivial but useful .. so thought of sharing.
(defmacro limit [max-recurs loop-expr]
(let [[_ bindings & body] loop-expr
counter (gensym)
transformer (fn transformer [form]
(if-not (seq? form) form
(let [[op & operands :as form] form]
(cond
(= op 'loop) `(limit ~max-recurs ~form)
(= op 'recur) `(recur ~@(conj (vec
operands) `(inc ~counter)))
:default (clojure.walk/walk transformer
identity form)))))]
`(loop ~(into bindings [counter 0])
(if (> ~counter ~max-recurs) (throw (Exception. "loop limit
exceeded"))
(do ~@(clojure.walk/walk transformer identity body))))))
usage :
(limit 1000 (loop [a 10]
(if (= (mod (rand-int 100) 5) 0) (recur (inc a))
(if (= (mod (rand-int 100) 5) 0) (recur (dec a))
(if (= (mod (rand-int 100) 5) 0) (recur (inc a))
(loop [x a y (* a a)]
(if (> x 100) (+ x y)
(recur (dec x) (inc y)))))))))
the above sexp will macro-expand to a form where none of the loop-recur
combination can recurse for more than 1000 iterations.
Merry Christmas and Happy New Year!!
Sunil.
--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.