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 <roman.perepeli...@gmail.com>
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 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

Reply via email to