Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
syntactic closures built on top of Clojure's macro system
Clojure
tag: syntactic-clos…

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
examples
src
test/syntactic_closure/test
.gitignore
README.md
project.clj

README.md

syntactic-closure

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.

Usage

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)

About

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.

Shorthand

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)

Resources

License

Copyright (C) 2012 OHTA Shogo

Distributed under the Eclipse Public License, the same as Clojure.

Something went wrong with that request. Please try again.