syntactic-closure
is a Clojure library that provides some facilities
to define hygienic macros with syntactic closures.
It aims to implement a hygienic macro system interoperable with Clojure's
macro system.
For details about syntactic closures, see Syntactic Closures or Chicken Scheme's wiki page.
Note: syntactic-closure
is still of alpha quality.
Add the following to your project.clj dependencies:
[syntactic-closure "0.1.0"]
Use via:
(use 'syntactic-closure.core)
or, for the shorthand, use via:
(use 'syntactic-closure)
As on some Scheme implementations, you can define hygienic macros using syntactic closures, like this:
(use 'syntactic-closure.core)
(define-syntax let1 [name init & body]
(sc-macro-transformer
(fn [env]
(quasiquote
(let [~name ~(make-syntactic-closure env nil init)]
~@(map #(make-syntactic-closure env [name] %) body))))))
(let1 x 10 (* x x))
In this case, the input name x
is automatically renamed.
(macroexpand '(let1 x 10 (* x x)))
;=> (let* [x403 10] (clojure.core/* x403 x403))
Using syntactic closures, you can also define anaphoric macros.
(define-syntax aif [test then else]
(sc-macro-transformer
(fn [env]
(let [it ~(make-syntactic-closure env nil test)]
(if it
~(make-syntactic-closure env '[it] then)
~(make-syntactic-closure env nil else))))))
Since Scheme-like interfaces are somehow verbose, syntactic-closure
namespace provides a simple shorthand for them (, though it is subject to change).
(use 'syntactic-closure)
(defsyntax let1 [name init & body]
(qq (let [~name ~^:? init]
~@^{:? name} body)))
(defsyntax aif [test then else]
(qq (let [it ~^:? test]
(if it
~^{:? 'it} then
~^:? else))))
For details about the shorthand, see Shorthand section below.
For more examples, see example code in the /examples
directory.
Each example includes both verbose and concise versions of code.
syntactic-closure
namespace provides qq
macro, which is almost the same
as quasiquote
except that in qq
form, the following shorthand can be used.
~^:? foo
is equivalent to~(make-syntactic-closure *env* nil foo)
- For any symbol
id
,~^{:? id} foo
is equivalent to~(make-syntactic-closure *env* [id] foo)
- For any list of symbols
ids
,~^{:? ids} foo
is equivalent to~(make-syntactic-closure *env* ids foo)
~@^:? foo
is equivalent to~@(map (bound-fn [x#] (make-syntactic-closure *env* nil x#)) foo)
- For any symbol
id
,~@^{:? id} foo
is equivalent to~@(map (bound-fn [x#] (make-syntactic-closure *env* [id] x#)) foo)
- For any list of symbols
ids
,~@{:? ids} foo
is equivalent to~@(map (bound-fn [x#] (make-syntactic-closure *env* ids x#)) foo)
- Syntactic Closures
- A Syntactic Closures Macro Facility
Copyright (C) 2012 OHTA Shogo
Distributed under the Eclipse Public License, the same as Clojure.