(use '[clojure.contrib.trace])
(dotrace [str] (reduce str [\a \b]))
In a nutshell:
That's because trace-fn-call, which is the thing dotrace uses to wrap the functions to be traced, uses str to produce the nice TRACE foo => val output.
Extended explanation:
The dotrace macro does its magic by installing a thread binding for each Var holding a function to be traced; in this case, there is one such Var, clojure.core/str. The replacement looks roughly like so:
(let [f ##'str]
(fn [& args]
(trace-fn-call 'str f args)))
The trace-fn-call, to quote its docstring, "Traces a single call to a function f with args.". In doing so, it calls the traced function, takes note of the return value, prints out a nice informative message of the form TRACE foo => val and returns the value obtained from the traced function so that regular execution may continue.
As mentioned above, this TRACE foo => val message is produced used str; however, in the case at hand, this is actually the function being traced, so a call to it leads to another call to trace-fn-call, which makes its own attempt to produce the tracing output string using str, which leads to another call to trace-fn-call... ultimately leading to the stack blowing up.
A workaround:
The following modified versions of dotrace and trace-fn-call should work fine even in the presence of weird bindings for core Vars (note that futures may not be scheduled promptly; if that's a problem, see below):
(defn my-trace-fn-call
"Traces a single call to a function f with args. 'name' is the
symbol name of the function."
[name f args]
(let [id (gensym "t")]
#(future (tracer id (str (trace-indent) (pr-str (cons name args)))))
(let [value (binding [*trace-depth* (inc *trace-depth*)]
(apply f args))]
#(future (tracer id (str (trace-indent) "=> " (pr-str value))))
value)))
(defmacro my-dotrace
"Given a sequence of function identifiers, evaluate the body
expressions in an environment in which the identifiers are bound to
the traced functions. Does not work on inlined functions,
such as clojure.core/+"
[fnames & exprs]
`(binding [~#(interleave fnames
(for [fname fnames]
`(let [f# #(var ~fname)]
(fn [& args#]
(my-trace-fn-call '~fname f# args#)))))]
~#exprs))
(Rebinding trace-fn-call around a regular dotrace apparently doesn't work; my guess is that's because of clojure.* Var calls still being hard-wired by the compiler, but that's a separate matter. The above will work, anyway.)
An alternative would be to use the above my-dotrace macro together with a my-trace-fn-call function not using futures, but modified to call custom replacements for the clojure.contrib.trace functions using the following in place of str:
(defn my-str [& args] (apply (.getRoot #'clojure.core/str) args))
The replacements are straightforward and tedious and I omit them from the answer.
Related
user=> (def v-1 "this is v1")
user=> (def v-2 "this is v2")
user=> (defmacro m [v] (symbol (str "v-" v)))
user=> (m 1)
"this is v1"
user=> (m 2)
"this is v2"
user=> (let [i 2] (m i))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: v-i in this context, compiling:(NO_SOURCE_PATH:73:12)
Can I write a macro let both
(m 2)
and
(let [i 2] (m i))
get "this is v2" ?
This is possible without a macro:
(defn m [v] (var-get (resolve (symbol (str "v-" v)))))
(m 1) ;; => "This is v1"
(let [i 2] (m i)) ;; => "This is v2"
You can use a macro too if you want:
(defmacro m [v] `#(resolve (symbol (str "v-" ~v))))
A plain function seems much more likely to be what you want.
First, though, to address the original question, if you wanted to insist on using a macro, macros are regular functions that happen to be called at compile time, so you can look up a Var using its symbolic name and obtain its value using deref just like you could at (your application's, as opposed to your macro's) runtime:
(defmacro var-value [vsym] #(resolve vsym))
(def foo 1)
(var-value foo)
;= 1
(macroexpand-1 '(var-value foo))
;= 1
Note that the above 1 is the actual macroexpansion here. This is different to
(defmacro var-value [vsym] `#(resolve ~vsym))
in that the latter expands to a call to resolve, and so the lookup given that implementation is postponed to your app's runtime.
(macroexpand-1 '(var-value foo))
;= (clojure.core/deref (clojure.core/resolve foo))
So this code will just be inlined wherever you call the macro.
Of course the macro could also expand to a symbol – e.g.
(defmacro prefixed-var [suffix]
`(symbol (str "v-" ssuffix)))
will produce expansions like v-1 (for (prefixed-var 1)) etc.
Going back to the subject of the suitability of macros here, however, if you use a macro, all the information that you need to produce your expansion must be available at compile time, and so in general you cannot use the values of let / loop locals or function arguments in your expansion for the fundamental reason that they don't have any fixed value at compile time.1
Thus the cleanest approach would probably be to wrap a resolve call in defn and call the resulting function – although of course to know for sure, we'd need to know what problem you were trying to solve by introducing a macro that performs a Var lookup.
1 Except if statically assigned constant values, as in the example given in the question text; I'm assuming you're thinking of using runtime values of locals in general, not just those that whose initialization expressions are constant literals.
I am trying to print the documentation for all functions in a given namespace by invoking the following expression in a REPL:
(doseq
[f (dir-fn 'clojure.repl)]
(doc f))
However the invocation of this expression returns nil without printing the documentation to the REPL. I know this might have to do with doc being a macro, but I'm a Clojure novice and am not entirely sure how to understand the problem.
Why does this expression return nil without printing the documentation?
How can this expression be modified so that it prints the documentation for each function in a given namespace?
Thanks!
Update: Combined both provided answers:
(defn ns-docs [ns']
(doseq [[symbol var] (ns-interns ns')]
(newline)
(println symbol)
(print " ")
(println (:doc (meta var)))))
(ns-docs 'clojure.repl)
I would, instead, start here:
The Clojure CheatSheet
ClojureDocs.org
Clojure-Doc.org (similar name, but different)
The API & Reference sections at Clojure.org
Note that doc is in the namespace clojure.repl, which reflects its intended usage (by a human in a repl). Here is some code that will also iterate on a namespace & print doc strings (using a different technique):
(doseq [[fn-symbol fn-var] (ns-interns 'demo.core)]
(newline)
(println fn-symbol)
(println (:doc (meta fn-var))))
where demo.core is the namespace of interest.
Note that ns-interns gives you both a symbol and var like:
fn-symbol => <#clojure.lang.Symbol -main>
fn-var => <#clojure.lang.Var #'demo.core/-main>
The meta function has lots of other info you may want to use someday:
(meta fn-var) =>
<#clojure.lang.PersistentArrayMap
{ :arglists ([& args]),
:doc "The Main Man!",
:line 9, :column 1,
:file "demo/core.clj",
:name -main,
:ns #object[clojure.lang.Namespace 0x14c35a06 "demo.core"]}>
While this probably won't help you with answering your question, the problem of evaluating macro's comes up a lot when you are learning Clojure.
Macros are responsible for the evaluation of their arguments. In this case clojure.repl/doc will ignore the current lexical context and assume that the symbol f that you're giving it is the name of a function you want to see the documentation for. It does this because it's intended to be used at the REPL, and is assuming you wouldn't want to type quotes all the time.
As f doesn't exist, it prints nothing. Then doseq returns nil, since it exists to do something for side effects only - hence starting in do. In order to pass an argument to a macro that refuses to respect the lexical context like this, you need to write the code for each element in the list.
You can do this by hand, or by constructing the code as data, and passing it to eval to execute. You can do this in an imperative style, using doseq:
(doseq [f (ns-interns 'clojure.repl)]
(eval `(doc ~(symbol "clojure.repl" (str (first f))))))
or in a slightly more Clojurey way (which will allow you to see the code that it would execute by removing eval from the end and running it at the REPL):
(->> (ns-interns 'clojure.repl)
(map #(list 'clojure.repl/doc (symbol "clojure.repl" (str (first %)))))
(cons `do)
eval)
In both of these we use quote and syntax-quote to construct some code from the list of symbols reflected from the namespace, and pass it to eval to actually execute it. This page on Clojure's weird characters should point you in the right direction for understanding what's going on here.
This an example of why you shouldn't write macro's, unless you've got no other options. Macro's do not compose, and are often difficult to work with. For a more in depth discussion, Fogus's talk and Christophe Grand's talk are both good talks.
Why does this expression return nil without printing the documentation?
Because the doc macro is receiving the symbol f from your loop, instead of a function symbol directly.
How can this expression be modified so that it prints the documentation for each function in a given namespace?
(defn ns-docs [ns']
(let [metas (->> (ns-interns ns') (vals) (map meta) (sort-by :name))]
(for [m metas :when (:doc m)] ;; you could filter here if you want fns only
(select-keys m [:name :doc]))))
(ns-docs 'clojure.repl)
=>
({:name apropos,
:doc "Given a regular expression or stringable thing, return a seq of all
public definitions in all currently-loaded namespaces that match the
str-or-pattern."}
...
)
Then you can print those maps/strings if you want.
Originally motivated by the following question: Mapped calls to clojurescript macro
Suppose you want to create many similar functions automatically (i.e. without hand-writing them all). Suppose we have some pre-existing functions and we want wrap them with handlers for a callback of some sort:
(defn do-foo [] (println "I foo'ed"))
(defn do-bar [] (println "I bar'ed"))
(defn do-baz [] (println "I baz'ed"))
(defn manual-on-foo [] (do-foo))
(defn manual-on-bar [] (do-bar))
(defn manual-on-baz [] (do-baz))
(println "Calling manual-on-* functions")
(manual-on-foo)
(manual-on-bar)
(manual-on-baz)
with results:
Calling manual-on-* functions
I foo'ed
I bar'ed
I baz'ed
We want to generate the wrapper functions automatically instead of manually.
You might think you need a macro to create this function, and that is one solution. However, a weakness of macros is that they cannot be passed as arguments to another function such as map. Thus, we could write a macro like:
(generate-fn :foo) ;=> creates `on-foo` w/o hand-writing it
but the following would fail:
(map generate-fn [:foo :bar :baz])
How can we automate the generation of these functions?
Overview
While you can't use map with a macro, you could write a second macro to perform this function. This may, in turn, require writing a third macro, etc, which is the origin of the phrase "Macros All the Way Down" as described in Clojure for the Brave and True and other places.
A similar question was answered here by using Clojure's intern function. Our problem is a little different than that question, since here we use intern in two different ways:
To create a global var like with def or defn
To access the value of a global var using var-get
Function Solution
Using intern allows us to write the following code to automatically generate the on-* functions without using macros:
(defn generate-onstar-f
[event-kw]
(let [
event-str (name event-kw)
do-fn-sym (symbol (str "do-" event-str))
on-fn-sym (symbol (str "on-" event-str))
new-fn (fn on-fn-sym []
(let [the-var (intern 'tst.clj.core do-fn-sym) ; get the var the symbol 'do-fn-sym' points to
the-fn (var-get the-var) ] ; get the fn the var is pointing to
(the-fn))) ]
(intern 'tst.clj.core on-fn-sym new-fn) ; create a var 'on-fn-sym' pointing to 'new-fn'
(println "Created" on-fn-sym)))
(println \newline "*** generating functions ***")
(mapv generate-onstar-f [:foo :bar :baz]) ; creates and interns a functions: my-foo, my-bar, my-baz
(println \newline "Calling automatically generated on-* functions")
(on-foo)
(on-bar)
(on-baz)
with results:
*** generating functions ***
Created on-foo
Created on-bar
Created on-baz
Calling automatically generated on-* functions
I foo'ed
I bar'ed
I baz'ed
So we see that we created the functions on-foo, on-bar & on-baz which, in turn, call the global do-foo, do-bar, & do-baz functions. And we didn't need to use macros!
In Clojure, the var is somewhat of an invisible "middle-man" between a symbol like on-foo and the value it points to (a function in this example). For more information please see the relate post:
When to use a Var instead of a function?
Macro Solution
As mentioned previously, one could use a macro to invoke another macro, side-stepping the problem that macros can't be used with higher-order-functions (HOF) like map. Here we define a new macro run-macro, to replace the map HOF we can't use with generate-onstar-f:
(defmacro generate-onstar-m
[event-kw]
(let [event-str (name event-kw)
do-fn-sym (symbol (str "do-" event-str))
on-fn-sym (symbol (str "on-" event-str "-m"))]
(println "Creating" on-fn-sym)
`(defn ~on-fn-sym []
(~do-fn-sym))))
(println \newline "Using Macro")
(generate-onstar-m :foo)
(on-foo-m)
(defmacro run-macro
"Run the specified macro once for each arg"
[root-macro args]
`(do
~#(forv [item args]
`(~root-macro ~item))))
(println \newline "Generating on-*-m functions using `run-macro`")
(run-macro generate-onstar-m [:foo :bar :baz])
(on-foo-m)
(on-bar-m)
(on-baz-m)
with results:
Using Macro
Creating on-foo-m
I foo'ed
Generating on-*-m functions using `run-macro`
Creating on-foo-m
Creating on-bar-m
Creating on-baz-m
I foo'ed
I bar'ed
I baz'ed
I want to define a macro that randomly chooses one of the given expressions and evaluates it. For example,
(equal-chance
(println "1")
(println "2"))
should print "1" half the time and "2" the other half.
I tried using,
(defmacro equal-chance
[& exprs]
`(rand-nth '~exprs))
but this returns one of the quoted forms, rather than evaluating it (i.e. it would return (println "1") rather than actually printing "1"). I cannot use eval because it does not preserve the bindings. For example,
(let [x 10] (eval '(println x)))
complains that it is unable to resolve symbol x.
Is there a way to evaluate a quoted form in the local scope? Or maybe there is a better way to go about this?
You can't evaluate a run-time value in a lexical environment that only exists at compile time. The solution is to use fn instead of quote and a function call instead of eval:
(defmacro equal-chance [& exprs]
`((rand-nth [~#(map (fn [e] `(fn [] ~e)) exprs)])))
The way this works is by expanding (equal-chance e1 e2 ...) into ((rand-nth [(fn [] e1) (fn [] e2) ...])).
Just don't quote the call to rand-nth or the expressions. This will do what you want:
(defmacro equal-chance
[& exprs]
(rand-nth exprs))
Given a list of names for variables, I want to set those variables to an expression.
I tried this:
(doall (for [x ["a" "b" "c"]] (def (symbol x) 666)))
...but this yields the error
java.lang.Exception: First argument to def must be a Symbol
Can anyone show me the right way to accomplish this, please?
Clojure's "intern" function is for this purpose:
(doseq [x ["a" "b" "c"]]
(intern *ns* (symbol x) 666))
(doall (for [x ["a" "b" "c"]] (eval `(def ~(symbol x) 666))))
In response to your comment:
There are no macros involved here. eval is a function that takes a list and returns the result of executing that list as code. ` and ~ are shortcuts to create a partially-quoted list.
` means the contents of the following lists shall be quoted unless preceded by a ~
~ the following list is a function call that shall be executed, not quoted.
So ``(def ~(symbol x) 666)is the list containing the symboldef, followed by the result of executingsymbol xfollowed by the number of the beast. I could as well have written(eval (list 'def (symbol x) 666))` to achieve the same effect.
Updated to take Stuart Sierra's comment (mentioning clojure.core/intern) into account.
Using eval here is fine, but it may be interesting to know that it is not necessary, regardless of whether the Vars are known to exist already. In fact, if they are known to exist, then I think the alter-var-root solution below is cleaner; if they might not exist, then I wouldn't insist on my alternative proposition being much cleaner, but it seems to make for the shortest code (if we disregard the overhead of three lines for a function definition), so I'll just post it for your consideration.
If the Var is known to exist:
(alter-var-root (resolve (symbol "foo")) (constantly new-value))
So you could do
(dorun
(map #(-> %1 symbol resolve (alter-var-root %2))
["x" "y" "z"]
[value-for-x value-for-y value-for z]))
(If the same value was to be used for all Vars, you could use (repeat value) for the final argument to map or just put it in the anonymous function.)
If the Vars might need to be created, then you can actually write a function to do this (once again, I wouldn't necessarily claim this to be cleaner than eval, but anyway -- just for the interest of it):
(defn create-var
;; I used clojure.lang.Var/intern in the original answer,
;; but as Stuart Sierra has pointed out in a comment,
;; a Clojure built-in is available to accomplish the same
;; thing
([sym] (intern *ns* sym))
([sym val] (intern *ns* sym val)))
Note that if a Var turns out to have already been interned with the given name in the given namespace, then this changes nothing in the single argument case or just resets the Var to the given new value in the two argument case. With this, you can solve the original problem like so:
(dorun (map #(create-var (symbol %) 666) ["x" "y" "z"]))
Some additional examples:
user> (create-var 'bar (fn [_] :bar))
#'user/bar
user> (bar :foo)
:bar
user> (create-var 'baz)
#'user/baz
user> baz
; Evaluation aborted. ; java.lang.IllegalStateException:
; Var user/baz is unbound.
; It does exist, though!
;; if you really wanted to do things like this, you'd
;; actually use the clojure.contrib.with-ns/with-ns macro
user> (binding [*ns* (the-ns 'quux)]
(create-var 'foobar 5))
#'quux/foobar
user> quux/foobar
5
Evaluation rules for normal function calls are to evaluate all the items of the list, and call the first item in the list as a function with the rest of the items in the list as parameters.
But you can't make any assumptions about the evaluation rules for special forms or macros. A special form or the code produced by a macro call could evaluate all the arguments, or never evaluate them, or evaluate them multiple times, or evaluate some arguments and not others. def is a special form, and it doesn't evaluate its first argument. If it did, it couldn't work. Evaluating the foo in (def foo 123) would result in a "no such var 'foo'" error most of the time (if foo was already defined, you probably wouldn't be defining it yourself).
I'm not sure what you're using this for, but it doesn't seem very idiomatic. Using def anywhere but at the toplevel of your program usually means you're doing something wrong.
(Note: doall + for = doseq.)