On Thu, Apr 28, 2011 at 6:36 AM, MohanR <radhakrishnan.mo...@gmail.com> wrote: > There should be a way to print the currently executing function and > the calling function logging purposes ? > > I believe Java has StackTraceElement[] to do this.
And therefore so does Clojure: user=> ((fn foo [] (map #(.getClassName %) (.getStackTrace (Throwable.))))) ("user$eval1738$foo__1739" "user$eval1738" "clojure.lang.Compiler" "clojure.lang.Compiler" "clojure.lang.Compiler" "clojure.core$eval" "user$eval1736" "clojure.lang.Compiler" "clojure.lang.Compiler" "clojure.core$eval" "clojure.main$repl$read_eval_print__5624" "clojure.main$repl$fn__5629" "clojure.main$repl" "clojure.lang.RestFn" "org.enclojure.repl.main$create_clojure_repl$repl_thread_fn__1247" "clojure.lang.AFn" "java.lang.Thread") You can get the "foo" out of the first element with enough regexp hackery I expect, but if handed a random function object it won't be as easy as if you are *inside* the function. If the function can be relied on to call one you pass it, then maybe you can: pass it a function that generates a traceback and stores it somewhere you can retrieve it, then look for a stack trace element below yourself. Even then it's tricky: (def st (atom nil)) (defn save-st [& _] (reset! st (map #(.getClassName %) (.getStackTrace (Throwable.))))) (defn get-mangled-name [f p-template] (apply f (map #(if (= % :here) save-st %) p-template)) (first (filter identity (map #(if (> (.indexOf %2 "get_mangled_name") -1) %1) @st (rest @st))))) (defn callifier [x f] (f x)) user=> (get-mangled-name callifier [3 :here]) "clojure.core$apply" Argh. user=> @st ("user$save_st" "clojure.lang.RestFn" "user$callifier" "clojure.lang.AFn" "clojure.lang.AFn" "clojure.core$apply" "user$get_mangled_name" ...) WTF? Seems a bit inefficient, but OK. (defn get-mangled-name [f p-template] (apply f (map #(if (= % :here) save-st %) p-template)) (first (filter identity (map #(if (> (.indexOf %2 "get_mangled_name") -1) %1) @st (drop 4 @st))))) user=> (get-mangled-name callifier [3 :here]) "user$callifier" Aha! user=> (get-mangled-name map [:here [1 2 3]]) "user$callifier" WTF??! user=> (reset! st ["foo" "bar" "baz" "quux" "get_mangled_name"]) ["foo" "bar" "baz" "quux" "get_mangled_name"] user=> (get-mangled-name map [:here [1 2 3]]) "foo" O-Damn: map is lazy, so save-st never gets called to overwrite the atom contents. OK, then: (defn get-mangled-name [f p-template] (let [x (apply f (map #(if (= % :here) save-st %) p-template))] (if (instance? clojure.lang.LazySeq x) (doall x))) (first (filter identity (map #(if (> (.indexOf %2 "get_mangled_name") -1) %1) @st (drop 4 @st))))) user=> (get-mangled-name map [:here [1 2 3]]) "clojure.lang.RT" AAAAAAA <img src=http://tinyurl.com/argggh> RRRGH! user=> @st ("user$save_st" "clojure.lang.RestFn" "clojure.core$map$fn__3695" "clojure.lang.LazySeq" "clojure.lang.LazySeq" "clojure.lang.RT" "clojure.core$seq" "clojure.core$dorun" "clojure.core$doall" "user$get_mangled_name" ...) (defn get-mangled-name [f p-template] (let [x (apply f (map #(if (= % :here) save-st %) p-template))] (if (instance? clojure.lang.LazySeq x) (doall x))) (let [a (fn [n] (first (filter identity (map #(if (> (.indexOf %2 "get_mangled_name") -1) %1) @st (drop n @st))))) y (a 4) n (if (= y "clojure.lang.RT") (a 7) y) ; mega hack! n (.substring n (inc (.indexOf n "$"))) i (.indexOf n "$")] (if (> i -1) (.substring n 0 (.indexOf n "$")) n))) user=> (get-mangled-name callifier [3 :here]) "callifier" user=> (get-mangled-name map [:here [1 2 3 4 5]]) "map" user=> (get-mangled-name filter [:here [1 2 3 4 5]]) "filter" It works! It w... user=> (get-mangled-name reduce [:here [1 2 3 4 5]]) "r" ...orks? user=> (get-mangled-name (fn foo [f z] (f z)) [:here [1 2 3 4 5]]) "eval2194" user=> (get-mangled-name #(+ %1 (%2 %1)) [3 :here]) #<CompilerException java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Number (NO_SOURCE_FILE:336)> *sob* So, it won't work if it's not a HOF that calls one of its arguments. It won't work if the fn is not top-level. It won't work if the function throws up when it sees save-st's output, though wrapping a catch-all try around (let [x ...]) might fix that. And of course if the function has side effects God help you. I don't think this approach is very workable for getting the names of arbitrary functions -- only yourself and functions that have called you. Better to just use the metadata, which works on every function for which get-mangled-name works, and won't mangle - to _. -- 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