I defined an unless macro as follows:
user=> (defmacro unless [expr body] (list 'if expr nil body))
#'user/unless
user=> (unless (= 1 2) (println "Yo"))
Yo
As you can see it works fine.
Now, in Clojure a list can be defined in two ways:
; create a list
(list 1 2 3)
; shorter notation
'(1 2 3)
This means that the unless macro can be written without the list keyword. However, this results in a Java exception being thrown:
user=> (unless (= 1 2) (println "Yo"))
java.lang.Exception: Unable to resolve symbol: expr in this context
Can someone explain why this fails?
'(foo bar baz) is not a shortcut for (list foo bar baz), it's a shortcut for (quote (foo bar baz)). While the list version will return a list containing the values of the variables foo, bar and baz, the version with ' will return a list containing the symbols foo, bar and baz. (In other words '(if expr nil body) is the same as (list 'if 'expr 'nil 'body).
This leads to an error because with the quoted version the macro expands to (if expr nil body) instead of (if (= 1 2) nil (println "Yo")) (because instead of substituting the macro's arguments for expr and body, it just returns the name expr and body (which are then seen as non-existent variables in the expanded code).
A shortcut that's useful in macro definitions is using `. ` works like ' (i.e. it quotes the expression following it), but it allows you to evaluate some subexpressions unquoted by using ~. For example your macro could be rewritten as (defmacro unless [expr body] `(if ~expr nil ~body)). The important thing here is that expr and body are unquoted with ~. This way the expansion will contain their values instead of literally containing the names expr and body.
Related
`a ``a and ```a gives the following
user=> `a
user/a
user=> ``a
(quote user/a)
user=> ```a
(clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote user/a))))
Since `a gives user/a, I'd anticipate ``a is the same as `user/a, which is user/a.
You are missing the evaluation step.
Let's first take a look at the simple quote:
user=> 'a
a
user=> ''a
(quote a)
user=> '''a
(quote (quote a))
user=> ''''a
(quote (quote (quote a)))
and so on. This is quite simple because it doesn't need to process the quoted form in any way except read it.
'a is read as (quote a), which evaluates to the symbol a.
''a is read as '(quote a), which is read as (quote (quote a)), which evaluates to the list (quote a), which is a list of the two symbols quote and a.
And so on.
Now, what does ` do that ' doesn't? It is more or less a template mechanism that
automatically qualifies symbols
automatically handles auto-gensym
evaluates things marked by ~ (or ~#) and re-inserts the results.
This means that it cannot just produce another quote form containing the following form, but has to produce an actual function call form at the call site (except in trivial cases). This form will mostly consist of sequence operations (list, cons, concat etc.) to assemble the template parts with the evaluated bits. If you then again quote that, you get to see those function call forms.
I'm in the process of translating some code from Scheme to Clojure.
The Scheme code uses a macro called pmatch (https://github.com/webyrd/quines/blob/master/pmatch.scm) to pattern match arguments to output expressions. Specifically, it allows for variable capture as follows:
(define eval-expr
(lambda (expr)
(pmatch expr
[(zero? ,e)
(zero? (eval-expr e)))
...
In this use example, some input expression to eval-expr, '(zero? 0), should match the the first case. The car of the list matches to zero? and the arity of the input matches. As a consequence, 0 is bound to ,e and passed to (zero? (eval-expr e)), and this expr is evaluated recursively.
In Haskell, which supports pattern matching natively, the code might translate to something like the following:
Prelude> let evalexpr "zero?" e = (e == 0) -- ignoring recursive application
Prelude> evalexpr "zero?" 0
True
In Clojure, I first tried to substitute pmatch with core.match (https://github.com/clojure/core.match), which was written by David Nolen and others, but, to my knowledge, this macro seems to
only support a single arity of arguments per use
only support explicit matching, rather than property based matching (available as guards)
Another option I'm trying is a lesser known macro called defun (https://github.com/killme2008/defun), which defines pattern matching functions. Here's an example:
(defun count-down
([0] (println "Reach zero!"))
([n] (println n)
(recur (dec n))))
I'm still exploring defun to see if it gives me the flexibility I need. Meanwhile, does anyone have suggestions of how to pattern match in Clojure with 1. flexible arity 2. variable capture?
Ignoring recursive application:
(ns test.test
(:require [clojure.core.match :refer [match]]))
(def v [:x 0])
(def w [:x :y 0])
(defn try-match [x]
(match x
[:x e] e
[:x expr e] [expr e]
))
(try-match v)
;; => 0
(try-match w)
;; => [:y 0]
;; Matching on lists (actually, any sequences)
(defn try-match-2 [exp]
(match exp
([op x] :seq) [op x]
([op x y] :seq) [op x y]))
(try-match-2 '(+ 3))
;; => [+ 3]
(try-match-2 '(+ 1 2))
;; => [+ 1 2]
See https://github.com/clojure/core.match/wiki/Overview for more details.
Additionally, I suggest you have a close look at Clojure destructuring. Lots of things can be done with it without resorting to core.match, actually your use case is covered.
I have been studying Clojure recently and I saw people using [], '[], () and '() at different places. In some case, [] and '[] are interchangeable.
So I wonder what is the different between these two symbols ?
'<expr> is reader syntax that expands to (quote <expr>). quote is a special form that says "don't evaluate this expression, but treat it as a literal instead." For example x evaluates to the value of x, whereas 'x evaluates to a symbol whose name is "x".
So '() expands to (quote ()), which evaluates to (). Likewise for []. So there is no difference for empty lists and empty vectors.
Now let's consider '(x), which is (quote (x)). This evaluates to (x), which is a literal list containing the symbol x. Another way of obtaining the same result would be to evaluate (list 'x). In contrast, evaluating (x) calls (or attempts to call) the function bound to x.
A similar argument holds for '[x] versus [x].
read up the topics macros and quoting
in short ' is a reader-macro which expands to (quote ..)
therefor '[] equals (quote [])
what it does - it supresses evaluation (i.e. here a is not defined)
user=> (quote [a])
[a]
user=> '[a]
[a]
; the following will fails since "a" is not bound
; there is no way to construct an array where the
; first element is the value of a
user=> [a]
CompilerException java.lang.RuntimeException:
Unable to resolve symbol: a in this context,
compiling:(NO_SOURCE_PATH:0:0)
I am attempting to write a macro that converts "generic" expressions into expressions evaluated for a particular given value.
Let us say that I have a vector of unevaluated expressions of the form,
'[(map? %)
(-> % :value string?)
(fn[x] (apply #(pos? %) (- x 2))]
I have a gensymed value v, that I wish to "pass" to the above expression at runtime. So, assume that v will be the name of the symbol used at compile time. I also wish to assert the converted expression. Basically, for the example above, I wish to convert the above vector expression into the form below. Note that I am passing the value v to % in the first two expressions, and to x in the third expression. The code below isn't correct, but only illustrates what I want to happen. I have no idea how to actually get v into any of the below expressions assertions.
'[(assert (map? %)) ;; % is equal to v
(assert (-> % :value string?)) ;; % is equal to v
(assert (fn[x] (apply #(pos? %) (- x 2)))] ;; x is equal to v
As a guiding example, I wish to be able to do what the :post part of a prepost-map? does on a defn expression. Any help is appreciated.
Don't do this with expressions. Instead, use functions. Then it's easy to just call each of the functions with whatever value you want.
The following two commands prints out the same thing in repl:
user=> (println "(foo bar)")
(foo bar)
nil
user=> (println (quote (foo bar))
(foo bar)
nil
So in this case, what's the difference between a quote and a string?
Edit:
(+ 3 2) and (+ (quote 3) 2) are the same. The docs say quote yields the unevaluated form (so maybe I'm answering my own question here but please verify) that a quote is an optimization with lazy evaluation?
They're indeed different things:
user=> (class '(foo bar))
clojure.lang.PersistentList
user=> (class "foo bar")
java.lang.String
Even if they might have an identical println result, they're not the same.
For the rest, #bmillare is right: you don't quote for laziness, you quote to express literals.
The reason they look the same is because println is specified to print the content of strings and quoted forms, including the name of the symbols, to stdout. If you want to print the forms as how they would look like when inputted to the reader, use prn (pr if you don't want the newline)
user=> (prn "(foo bar)")
"(foo bar)"
nil
user=> (prn (quote (foo bar)))
(foo bar)
nil
For the other question,
Quote is not an optimization with lazy evaluation. The reason you get (+ 3 2) and (+ (quote 3) 2) is that you are quoting a literal e.g. a number, a keyword, or a string. (http://clojure.org/reader) Literals are evaluated at read time, before the form is passed to the upper form. Another way to think of it is quoting literals simply is defined to be an identity.