Clojure Macros Tutorial - part 3: Syntax Quote (aka Backtick) in Clojure 【转载】

Clojure Macros Tutorial - part 3: Syntax Quote (aka Backtick) in Clojure

May 5, 2016 clojure

Clojure provides a powerful tool to allow the developer to write macros effectively. This tool is called “Syntax quote”.

This tool provide an elegant solution to the issues mentioned in how not to write macros in Clojure.

Syntax quote has 4 powerful features:

  1. fully-qualified symbols
  2. unquote with ~
  3. unquote splicing with ~@
  4. generated symbols with #

Here is the official documentation for syntax quote.

But this documentation is too cryptic.

In this article, we present this powerful tool in a much digestible way…

Dummies

Regular Quote

Before dealing with syntax quoting, let’s remember how the regular quote works.

There are two equivalent ways to quote a form either with quote or with '. The latter is much more convenient so we will use it.

It works recursively with any kind of forms and types: strings, maps, lists, vectors…

Let’s have a look at some examples:

'(a :a 1)
the evaluation will appear here (soon)...
'(a (b (c d (e f (g h) i) j)))
the evaluation will appear here (soon)...
'{:a (1 2 3) b (c d "x")}
the evaluation will appear here (soon)...

Syntax Quote - symbol resolution

Syntax quote is done with a backtick ```. It quotes a form and resolves symbols in the current context yielding a fully-qualified symbol. If the symbol doesn’t exist in the current namespace, it is resolved to the current namespace.

When we use the regular quote, there is no namespace resolution:

'(map)
the evaluation will appear here (soon)...

While with syntax quote, the symbol is resolved:

`(map)
the evaluation will appear here (soon)...

If a symbol exists in the current namespace, it is resolved there:

(ns my.quote)
(def a 123)
`(a)
the evaluation will appear here (soon)...

If a symbol cannot be resolved, it is also resolved in the current namespace:

`(b)
the evaluation will appear here (soon)...

Syntax Quote - unquote

With syntax quote, it’s possible to unquote part of the form that is quoted with ~. It allows you to evaluate part of the expression.

Without evaluation:

`(16 17 (inc 17))
the evaluation will appear here (soon)...

With evaluation:

`(16 17 ~(inc 17))
the evaluation will appear here (soon)...

Another one:

`(16 17 ~(map inc [16 17]))
the evaluation will appear here (soon)...

Syntax Quote - unquote splicing

But what if you want to unquote a list and insert its elements (not the list) inside the quoted form?

No problem, ~@ is your friend (his official name is unquote splicing). And ~@ is really a good friend as he knows to handle any kind of collection.

Without splicing:

`(16 17 ~(map inc [16 17]))
the evaluation will appear here (soon)...

With splicing:

`(16 17 ~@(map inc [16 17]))
the evaluation will appear here (soon)...

Other examples:

`(1 2 ~@[1 [2 3]])
the evaluation will appear here (soon)...
`(1 2 ~@#{1 2 3})
the evaluation will appear here (soon)...
`(1 2 ~@{:a 1 :b 2 :c 3})
the evaluation will appear here (soon)...

Syntax Quote - symbol generation

Inside syntax quote, you can generate unique symbol names by appending # to the symbol.

`(A#)
the evaluation will appear here (soon)...

The cool thing is that all the references to that symbol within a syntax-quoted expression resolve to the same generated symbol.

`(a b a# b#)
the evaluation will appear here (soon)...
`(a b a# b# a# b#)
the evaluation will appear here (soon)...
`{:a a# :b b# :c b#}
the evaluation will appear here (soon)...

There are other advanced features available inside syntax quote like ~', ~~and '~@.

We might write an article on it in the (near) future…

Clojure rocks!

Share: Twitter Facebook

Subscribe to Yehonathan Sharvit newsletter

Get the latest and greatest from Yehonathan Sharvit delivered straight to your inbox every week.

Email Address

May 4, 2016

Clojure Macros Tutorial - part 2: how not to write macros

Clojure

May 9, 2016

Clojure Macros Tutorial - part 4: Examples of cool macros #cljklipse @viebel

Clojure

TAGS

algo brainfuck c++ clojure clojurescript compiler dop golang graph html java javascript kids klipse lambda-calculus lambdacalculus lisp lua maths oblivion ocaml php prolog python react reagent reasonml ruby scheme sql theory visualization

YEHONATHAN SHARVIT © 2022.

Back to top

posted @ 2022-10-18 20:15  堕落门徒  阅读(25)  评论(0编辑  收藏  举报