How to correctly use syntax-quote and unquote inside of `defmacro` - macros

I have a simple macro:
(defmacro macrotest [coll]
`(let [result# ~(reduce + coll)]
result#))
Why, if this code works:
(macrotest [1 2 3])
doesn't this code work?
(def mycoll [1 2 3])
(macrotest mycoll)

Symbols are not the same as the value they point to.
One of the important considerations about macros is not just how they create new code, but also how they handle the arguments you pass in.
Consider this:
(def v [1 2 3])
(somefunction v)
The argument v passed to this function does not arrive inside the function as a symbol, v. Instead, because this is a function call, the arguments are evaluated first, then their resulting value is passed into the function. So the function will see [1 2 3].
But macros are not like this, though it is easy to forget. When you call:
(somemacro v)
v is not evaluated and does not pass in [1 2 3]. Inside the macro, all you get is a symbol, v. Now, your macro can emit the symbol you passed in, in the code the macro creates, but it cannot do anything with the value of v unless you add an extra level of evaluation using eval (see footnote -- not recommended).
When you unquote the macro argument, you get a symbol, not a value.
Consider this example:
user> (def a 5)
#'user/a
user> (defmacro m [x] `(+ ~x ~x))
#'user/m
user> (m a)
10
user> (macroexpand '(m a))
(clojure.core/+ a a)
user> (defmacro m [x] `~(+ x x))
#'user/m
user> (m a)
ClassCastException clojure.lang.Symbol cannot be cast to java.lang.Number clojure.lang.Numbers.add (Numbers.java:126)
This would be like trying to do this at the REPL: (+ 'a 'a) Adding symbols, not adding the values those symbols point to.
You might look at these two different definitions of the macro m and think they are doing the same thing. But in the second one, there is an attempt to do something with the symbol x, to do addition with it. In the first macro, the compiler is not asked to do anything with x. It merely is told to emit the addition operation, which will then be actually processed at runtime.
Remember that the point of a macro is to create code not perform runtime activity that a function would do. The code that is created is then immediately run (via implicit eval), so it's easy to forget this separation, but they are two distinct steps.
As a final exercise, pretend you are a compiler. I want you to tell me right now what is the resulting value of this code:
(* t w)
Well? It's impossible. There is no way you can tell me the answer to this question because you have no idea what t and w are. However, later, at runtime, when these presumably have a value, then it will be easy.
And that's what macros do: they output stuff for the runtime to handle.
(Very much not recommended but to help further describe what's happening, this works:)
user> (def a 1)
user> (defmacro m [x] `~(+ (eval x) (eval x)))
user> (m a)
2

Related

What is the proper way to construct a clojure macro from lists of symbols?

Imagine the following code to dynamically create a macro:
(def a (list '+ 1 2))
(def b (list '- 10 5))
(def c (list '/ 22 2))
(defmacro gg [h]
(let [k# `~h]
k#))
The intent is to pass a vector of symbols to a macro, do some evaluation on each element of the vector such that it returns a nice macro-esque form, then have the macro combine them into a nice macro and evaluate it. The above example works all except the actual evaluation.
When I run it I get:
(gg [a b c])
=> [(+ 1 2) (- 10 5) (/ 22 2)]
What is the secret to passing a symbol that is a list of symbols and getting a macro to evaluate them? I have tried lots of combinations of quoting and have yet to hit the right one.
The real purpose of this question is to build an Archimedes Ogre query based on a definition of a path through the graph. If someone has an example of that, I would be grateful.
EDIT:
(defmacro gg2 [h]
`(do ~#(map identity h)))
(macroexpand '(gg2 [a b c]))
=> (do a b c)
(gg2 [a b c])
=> (/ 22 2)
I was hoping to get 11 rather than the form.
You don't need a macro. Macros don't do what you're looking for here. What you are looking for is eval.
(def a '/)
(def b 22)
(def c 2)
(eval (list* [a b c]))
=> 11
Of course, you can write a macro which expands into (eval (list* ...)) if you want. It could just as well be a function though.
This is a very common mistake when starting out with macros; trying to write a macro which depends on the run-time value of its arguments. Macros run at compile-time, and generally the values of the symbols which you pass to a macro are not yet available when the macro is expanded.
About the use of eval, some cautions are in order. No one said it better than Paul Graham:
Generally it is not a good idea to call eval at runtime, for two reasons:
It’s inefficient: eval is handed a raw list, and either has to compile it on the spot, or evaluate it in an interpreter. Either way is slower than compiling the code beforehand, and just calling it.
It’s less powerful, because the expression is evaluated with no lexical context. Among other things, this means that you can’t refer to ordinary variables visible outside the expression being evaluated.
Usually, calling eval explicitly is like buying something in an airport gift-shop. Having waited till the last moment, you have to pay high prices for a limited selection of second-rate goods.

What would the consequences be of allowing special forms to be treated as normal values?

I discovered that special forms can not be passed as arguments or saved in variables, both in Clojure:
user=> (defn my-func
[op]
(op 1 2 3))
#'user/my-func
user=> (my-func +)
6
user=> (my-func if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:5)
user=> (def my-if if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:9)
and in Racket/Scheme:
> (define (my-func op)
(op 1 2 3))
> (my-func +)
6
> (my-func if)
if: bad syntax in: if
> (define my-if if)
*if: bad syntax in: if
That's cool, I'm fine with that, I know that I can just write a function to wrap a special form and then pass that function.
But I'd like to know why Lisps have this restriction, and what negative consequences allowing this would have. Are they any major dialects that do allow that?
It makes evaluation more complicated and compilation hard.
If you have a form (a b c), then you need to resolve at runtime the value of a and then apply it somehow to the forms b and c.
The simpler model of a few limited number of special forms and otherwise strict evaluation is then gone.
See also: FEXPR
Special forms are not functions: functions take values as arguments, whereas special forms take forms. For example, look at your example of if:
(if 1 2 3)
Okay, that's easy, since 2 and 3 are already values. But what about this?
(define (modadd a b n)
(if (zero? n) #f (modulo (+ a b) n)))
In this case, the if is actually receiving the #f and (modulo (+ a b) n) as forms, not as values. And this is important! (modulo x n) will fail if n is 0: that is why it's left unevaluated until we know that n is not 0.
The trouble with being able to pass special forms as first-class objects is that higher-order functions cannot call those objects using predictable semantics: is it a function object, so that you're passing in values, or is it a special form, so that you're passing in forms? This gets to be a huge mess.
Yes, you can write a wrapper function, like my modadd, that encapsulates if. However, there is no way you can just reimplement if as a function, while still preserving the only-evaluate-one-of-the-branches behaviour.

Generalized Threading Macro in Clojure

Note: this is NOT about concurrency. This is about the thread macro.
I know that -> puts the object at the 2nd position and ->> puts the argument at the last position.
Now, I'm curious, much like the short hand notation of #( ... % ) for functions, is there a short hand notation for threads that lets me place the argument at arbitrary location?
The goal would be that instead of having a fixed location for the thread to run through ... I can write arbitrary forms, and insert %% at special places, and the %% is where the thread gets inserted.
Thanks!
There is now a generalized threading macro in Clojure since 1.5 called as->.
This tweet gives an example of how it works: https://twitter.com/borkdude/status/302881431649128448
(as-> "/tmp" x
(java.io.File. x)
(file-seq x)
(filter (memfn isDirectory) x)
(count x))
First 'x' is bound to "/tmp" and a file is made out of it. 'x' is rebound again to the resulting file and a put through the 'file-seq' function, etc.
The 'diamond wand' from Swiss Arrows library would do what you're asking for:
(-<> 0
(* <> 5)
(vector 1 2 <> 3 4))
; => [1 2 0 3 4]
That said, it isn't something you end up needing often (or ever in my Clojure experience)
In case anyone else comes across this, there is a reason the provided macros exist, but an arbitrary placement one does not: the latter would lead to poor API design.
The -> macro places the argument in the first position. This corresponds to functions that work on some subject argument, e.g., conj, assoc.
The ->> macro places the argument in the last position. This corresponds to functions that work on sequences, e.g., map, reduce.
Design your APIs well, and you'll be less likely to need such a macro.
There was a library that provided this feature, but I forgot where. It might of been in the deprecated clojure-contrib. It was the -$> macro.
But you could derive one from clojure's core -> macro to make the one you're looking for:
(defmacro -$>
([x] x)
([x form] (if (seq? form)
(with-meta (map #(if (= %1 '$) x %1) form) (meta form))
(list form x)))
([x form & more] `(-$> (-$> ~x ~form) ~#more)))
And use $ to indicate the insertion point:
user=> (-$> 2 str (identity $) (println $))
2
nil
Technically, you could use multiple $ in one form. But this implementation suffers from expanding the same form multiple times (in exchange for simplicity).

Splicing unquote for non-literal sequences

This question is a based on a limitation of this answer.
If I have a macro that uses splicing unquote like this:
(defmacro instantiate [klass values]
`(new ~klass ~#values))
It will only work if values is a literal sequence or seq-able.
If it is passed a var holding a sequence like:
(def v [1 2 3])
(macroexpand '(instantiate Person v))
Then the output would be an error indicating that v is not a sequence.
Even a function call would be interpreted as a list:
(defn vf [] [1 2 3])
(macroexpand '(instantiate Person (vf)))
user=>(new Person vf)
My question is: Is there any way to use the splicing unquote in Clojure macros in those two cases where the sequence to be spliced isn't a literal?
Macros receive their arguments unevaluated, so the behavior you are seeing is as intended.
Macros are expanded at compile time, not run time. The values of any variables passed into a macro may not be available at compile time, so dirty hacks like using eval will not work in the general case. Don't create macros that require such tricks.
splicing quotes save a lot of time in almost all cases, except when they dont work, then you need to do things the old fashioned way...
(defmacro instantiate [klass values]
`(new ~klass ~#values))
could become
(defmacro instantiate [klass values]
(concat (list 'new klass) (if (seq? values)
values
(list values))))
user=> (macroexpand '(instantiate asdf (1 2 3)))
(new asdf 1 2 3)
user=> (macroexpand '(instantiate asdf 1))
(new asdf 1)

Clojure macros and symbol binding

not sure how to express this..
I've written a macro which takes two arguments. The first one essentially contains identifiers for generating a let expression. The second is the code to use inside the let expression (it wants to have access to these identifiers).
An example:
(match (Add {ast-> x}) (println x))
When the second argument is raw code, things work nicely. x binds to the x defined in the let expression (when macroexpanded it just shows as x). However, when the second argument is a macro which generates (println x), x expands to something like user/x.
Any good ideas on how to fix this?
It sounds like your second macro is defined as:
(defmacro foo
[]
`(println x))
This is incorrect as x will be namespace qualified. The correct version of the second macro in this case would be:
(defmacro foo
[]
`(println ~'x))
Now the x in the println call will be a literal x symbol and not namespace qualified.