Hi Roman,
as far as I understand, the Clojure compiler is doing some
optimizations for recursive functions to save the variable lookup.
This means that you have to explicitly write the recursive call as
(#'fact (dec n)) if you want to dynamically rebind the function.
Somehow this doesn't feel right for a dynamic language.
Clojure 1.3, which cannot dynamically rebind variables unless they are
explicitly marked as ^:dynamic, introduced with-redefs to solve this
problem. In Clojure 1.3 you're example works as expected if you use
with-redefs instead of binding in the definition of fact-with-logging.
In case you can't use Clojure 1.3, you might be able to use the source
code of with-redefs in order to achieve a similar effect in 1.2.
Though, I haven't tested it.
Best,
Nils
On Nov 30, 9:11 pm, Roman Perepelitsa <[email protected]>
wrote:
> Hello,
>
> I'm trying to intercept each call to a recursive function in order to
> insert logging. It works on the first invocation but not on others. What am
> I missing?
>
> (defn fact [n]
> (if (< n 2)
> 1
> (* n (fact (dec n)))))
>
> ; Given function f, returns another function that
> ; does the same as f but also prints the arguments.
> (defn with-logging [f]
> (fn [& rest]
> (do
> (println (str rest))
> (apply f rest))))
>
> ; Factorial that prints its argument on each call.
> (defn fact-with-logging [n]
> (binding [fact (with-logging fact)] (fact n)))
>
> ; This prints (5) but not (4)...(1). Why?
> (fact-with-logging 5)
>
> Roman.
--
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