Difference between #^{...} and ^{...} metadata in Clojure? - clojure

Consider
(defn f ^{:foo "bar"} [x] (* x x))
and
(defn g #^{:foo "bar"} [x] (* x x))
Both compile and run.
I have two questions: first, why do (meta f) and (meta g) produce only nil? I would have expected them to produce {:foo "bar"}; i.o.w., am I just completely out to lunch on metadata and have I defined some kind of garbage out there?
Second, what is the difference between the two syntaces for the metadata? It looks like the second one is a "tagged literal," something to do with edn, the extended data notation, but I can't quite noodle it out without some more context or examples.

The #^ metadata reader macro was replaced with ^ in clojure 1.2. While there is currently no difference between the two, the old form is deprecated and you should be using ^ exclusively.
The metadata literal should come before the item it is to be attached to:
(defn ^{:foo "bar"} f [x] (* x x))
Another thing to keep in mind is that the metadata in the above definition isn't attached to the function, it is attached to the var that refers to the function. You can get the metadata of the f var with:
(meta (var f))
Or using the var reader macro:
(meta #'f)

Related

Dynamic symbols in Clojure Macro/Special Form

I have a question regarding how to define functions/macros which call other macros or special forms but where one of the symbols passed in needs to be dynamic.
The simplest version of this question is described below:
We can define variables using def
(def x 0)
But what if we wanted the name x to be determined programmatically so that we could do the equivalent of?
(let [a 'b]
(our-def a 3)) => user/b
We could try to define a function
(defn defn2 [sym val]
(def sym val))
However it does not do what we want
(def2 'y 1) => #'user/sym
At first it seems like a macro works (even though it seems like it would be unnecessary)
(defmacro def3 [sym val]
`(def ~sym ~val))
(def3 z 2) => user/z
but it is just superficial, because we're really right back where we started with regular def.
(let [a 'b]
(def3 a 3)) => user/a
I can do it if I use eval, but it doesn't seem like eval should be necessary
(defn def4 [sym val]
(eval `(def ~sym ~val)))
(let [a 'b]
(def4 a 4)) => user/b
If there are other built-in commands that could achieve this particular example, they are not really what I am looking for since def is just to show a particular example. There are macros more complicated than def that I might want to call and not have to worry about how they were internally implemented.
First: The right way to do this is to use macro that starts with def... since this is the way people have been doing defs and is of little surprise to the user.
To answer you question: Use intern:
(def foo 'bar)
(intern *ns* foo :hi)
(pr bar) ;; => :hi
(intern *ns* foo :hi2)
(pr bar) ;; => :hi2
If you want to use macros do this:
(def z 'aa)
(defmacro def3 [sym val]
`(def ~(eval sym) ~val))
(def3 z 2)
(pr aa) ;; => 2

Why can symbol in eval not be resolved?

Why does
((fn[x] (eval (symbol "x"))) 1)
blow up Unable to resolve symbol: x in this context?
I expected it to behave just like
((fn[x] x) 1)
and evaluate to 1.
(How) Can the former be fixed to return 1 using eval?
eval does not use the lexical scope where it is called (as introduced by fn, let, or loop), it only sees vars as mapped via the current namespace (bound to the var *ns*).
Introducing a lexical binding into an eval context will involve wrapping the form in a let manually, or using undocumented implementation dependent host interop to find and provide lexical bindings to the eval context.
An example of wrapping in a let manually (this will only work when x is something readable by the Clojure reader):
user=> (def x 0)
#'user/x
user=> (let [x 42] (eval 'x)) ; gets the global value of x, not local
0
user=> (let [x 42] (eval (list 'let ['x (list 'quote x)] 'x))) ; manually getting the local
42

How to resolve interned vars within a let?

The following code compiles fine:
(intern *ns* 'a 1) ;#'user/a
(intern *ns* 'b (+ a 1)) ;#'user/b
It also compiles in a do:
(do
(intern *ns* 'c 1)
(intern *ns* 'd (+ c 1)))
However compilation fails in a let (or any other binding form I have tried, including fn):
(let []
(intern *ns* 'e 1)
(intern *ns* 'f (+ e 1)))
;CompilerException java.lang.RuntimeException: Unable to resolve symbol: ‘e in this context, compiling:(NO_SOURCE_PATH:2:5)
It looks like the interns are not performed in this case until after the let completes. My only work around instead of using locals is to mutate atoms or use alter-var-root.
Why doesn't intern work inside let, et al. the same way it does in do? Is there a way to force the intern to complete inside a let so that the above example compiles? (BTW, macros are not an option as I want to access runtime information in my binding form using ns-map)
You can't write that, because only do gets the special treatment causing its subforms to each be compiled and evaluated in order, rather than all compiled at once and then all evaluated. But really, this is a weird way to do what you are trying to do: these manual calls to intern are quite unusual. Why not simply put locals into your let, and then intern whichever ones you want to keep? let has exactly the property you need, in that previously-defined symbols are visible in the next binding.
(let [e 1, f (+ e 1)]
(intern *ns* 'e e)
(intern *ns* 'f f))
Another answer by #amalloy answers the "why" part of the question and suggests a workaround. If, for some reason, it is still important to refer to a value of an interned var, resolve function can be used:
(let []
(intern *ns* 'e 1)
(intern *ns* 'f (+ #(resolve 'e) 1)))
;; => #'user/f
e
;; => 1
f
;; => 2

Clojure: issues getting the symbol of a function in a looping context

Let's take that Clojure code:
(defn ^{:test-1 "meta-test-1"} fn-key-1
[x]
(eval nil))
(defn ^{:test-2 "meta-test-2"} fn-key-2
[x]
(eval nil))
(def some-map {fn-key-1 "test-1"
fn-key-2 "test-2"})
As you can see, the keys of my map are Symbols that refers to functions. I don't thing there is anything special there.
As you can see, when defining the map the keys of my map are Symbols that refers to functions. However, when they are read by the reader, then they get resolved to the function objects.
Now, what I want to do is to iterate over my some-map map to get the meta-data for each of the keys.
I was thinking doing this that way:
(defn some-fn
[m]
(doseq [[fn-key value] m]
(println (meta fn-key))))
However, what is being printed here is nil. This is expected since the meta-data is defining the symbol, and not the function. So, there is no meta-data attached to the function and it is why nil is being returned/printed.
So this lead to a question: is it possible to get the symbol that refers to my function "fn-key" in that context?
In that doseq loop, it appears that fn-key is a function and not the symbol of that function. What I need is a way to get the symbol of that function such that I can use (meta (get-symbol fn-key)).
Question Resolution
This question got resolved by defining the functions that way:
(def fn-key-1
(with-meta (fn [x] (eval nil)) {:foo "bar"}))
(def fn-key-2
(with-meta (fn [x] (eval nil)) {:foo "bar"}))
Revision of the Resolution
I revised the solution above to make it cleaner. In fact, if you were to type fn-key-1 in the REPL, you were to get an anonymous function reference such as #< clojure.lang.AFunction$1#15ab1764>. The problem with that is that it make things difficult to debug when you don't know what is being evaluated. To solve this issue, I changed the two function definitions to use this syntax, which resolve this issue:
(def fn-key-1 ^{:foo "bar"} (fn [x] (eval nil)))
(def fn-key-2 ^{:foo "bar"} (fn [x] (eval nil)))
Now, if we type fn-key-1 then we will get something like #<core$foo user.core$foo#66e37466> instead. At least, we have the namespace & symbol signature of this function object.
(def some-map {#'fn-key-1 "test-1"
#'fn-key-2 "test 2"})
fn-key-1 is resolved by the reader to the function object (which has no metadata to query). #'fn-key-1 resolves to the var itself, and holds the metadata.

How to get the metadata of clojure function arguments?

Is there a way to generically get metadata for arguments to a function in clojure? The answer posted in this question does not, actually, work in general:
user> (defn foo "informative dox!" [] 1)
#'user/foo
user> (defmacro get-docs [func] `(:doc (meta (var ~func))))
#'user/get-docs
user> (get-docs foo)
"informative dox!"
user> (get-docs (identity foo))
; Evaluation aborted.
user> (defn process-docs [f] (let [docs (get-docs f)] (reverse docs)))
; Evaluation aborted.
The second-to-last line doesn't work because you can't call var on the list (identity foo), and the last line doesn't even compile because the compiler complains about being unable to resolve f.
Most of the solutions for this problem I've found rely on the idea that you have access to the symbol in the function's definition, or something like that, so that you can do something like (resolve 'f) or (var f). But I want something that I can use on the argument to a function, where you don't know that information.
Essentially, I'd like an expression I can put in place of the question marks below to get the metadata of #'map:
(let [x map] (??? x))
its a mouthful though possible:
(let [x map]
(:doc (meta (second (first (filter #(and (var? (second %))
(= x (var-get (second %))))
(ns-map *ns*)))))))
produces the desired result:
"Returns a lazy sequence consisting of the result of applying f to the
set of first items of each coll, followed by applying f to the set
of second items in each coll, until any one of the colls is\n exhausted. Any remaining items in other colls are ignored. Function
f should accept number-of-colls arguments."
under the hood Namespaces are essentially maps of names to vars and the vars contain functions. you can search the contents of these vars for the one that matches the function you are seeking and then look at it's associated var and get the metadata from that var.