I like something along the lines of Python decorators[1] as
that keeps the logic of the function from being lost in the
instrumentation code.
E.g.
(def *verbose* true)
(defn print-decorate [f]
(fn [& args]
(println f "called with" args)
(apply f args)))
(defn foo [x] (* 2 x))
(when *verbose*
(def foo (print-decorate foo)))
With *verbose* true:
user=> (load-file "foo.clj")
#'user/foo
user=> (foo 2)
user.foo__2372@5388b5 called with (2)
4
With *verbose* false:
user=> (load-file "foo.clj")
nil
user=> (foo 2)
4
Perhaps this approach can be improvised further but
I myself am somewhat of a Clojure noob.
I suspect the boot.clj code (especially in the early part of
the file) may not be most ideomatic Clojure code as
Clojure is still booting itself.
On a somewhat related note. Getting the function name at the
Clojure prompt seems to work:
user=> (:name (meta (var foo)))
foo
However if I try to improvise print-decorate by putting
in the above approach, I get an exception while loading
the file.
(defn print-decorate [f]
(fn [& args]
(println (:name (meta (var f))) "called with" args)
(apply f args)))
clojure.lang.Compiler$CompilerException: foo.clj:5: Unable to resolve
var: f in
this context
Could someone explain what I am doing wrong here?
How can I get the function name at runtime in print-decorate?
Full exception log below.
Parth
[1]
http://www.ibm.com/developerworks/linux/library/l-cpdecor.html
user=> (load-file "foo.clj")
java.lang.Exception: Unable to resolve var: f in this context
clojure.lang.Compiler$CompilerException: foo.clj:5: Unable to resolve
var: f in this context
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3821)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyze(Compiler.java:3627)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:2630)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3816)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyze(Compiler.java:3627)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:2630)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3816)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyze(Compiler.java:3627)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:2630)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3816)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyze(Compiler.java:3627)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:
3340)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:3187)
at clojure.lang.Compiler$FnMethod.access$1200(Compiler.java:
3098)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:2729)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3812)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3804)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyze(Compiler.java:3627)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:
3340)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:3187)
at clojure.lang.Compiler$FnMethod.access$1200(Compiler.java:
3098)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:2729)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3812)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3804)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.access$200(Compiler.java:37)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:
335)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3814)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3804)
at clojure.lang.Compiler.analyze(Compiler.java:3654)
at clojure.lang.Compiler.analyze(Compiler.java:3627)
at clojure.lang.Compiler.eval(Compiler.java:3851)
at clojure.lang.Compiler.load(Compiler.java:4136)
at clojure.lang.Compiler.loadFile(Compiler.java:4103)
at clojure.lang.RT$3.invoke(RT.java:285)
at user.eval__2409.invoke(Unknown Source)
at clojure.lang.Compiler.eval(Compiler.java:3847)
at clojure.lang.Repl.main(Repl.java:75)
Caused by: java.lang.Exception: Unable to resolve var: f in this
context
at clojure.lang.Compiler$TheVarExpr$Parser.parse(Compiler.java:
457)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:3814)
... 50 more