Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/brandonbloom/metaclj
Staged compilation for Clojure through environment & special-form aware syntax-quoting.
https://github.com/brandonbloom/metaclj
clojure metaprogramming staging
Last synced: about 1 month ago
JSON representation
Staged compilation for Clojure through environment & special-form aware syntax-quoting.
- Host: GitHub
- URL: https://github.com/brandonbloom/metaclj
- Owner: brandonbloom
- License: epl-1.0
- Created: 2014-06-30T20:23:35.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2021-10-29T00:14:50.000Z (about 3 years ago)
- Last Synced: 2024-04-22T13:33:11.301Z (8 months ago)
- Topics: clojure, metaprogramming, staging
- Language: Clojure
- Homepage:
- Size: 34.2 KB
- Stars: 79
- Watchers: 7
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-clojure - metaclj - staged compilation (Awesome macros usage)
README
# Meta-Clojure
## Overview
Meta-Clojure provides staged compilation for Clojure. It includes a form of
syntax quoting that is aware of both local environments and special-forms.
Among other things, this makes many macros easier to write. Perhaps more
importantly, it simplifies control over when code gets evaluated or compiled.## Usage
```clojure
(require '[metaclj.core :refer [defmeta defbn syntax] :as meta])
```### Meta-Macros
The `defmeta` form is analogous to `defmacro`, but is expected to return
Syntax objects (forms plus their environments) instead of plain forms.```clojure
(defmeta my-if [test then else]
(syntax (if test then else)))
```Note that you don't need to unquote any of the parameters to `if`, since the
`syntax` form is aware of the meta-macro's environment.### Call-By-Name
Since it's common for macros to have a body that always templates code with
a syntax-quoter, the convenience macro `defbn` provides a way to create
"call-by-name" macros:```clojure
(defbn my-if [test then else]
(if test then else))
```Both versions of `my-if` have correct "lazy" behavior: they will only evaluate
one arm of the conditional.### Staged Compilation
The `meta/do` macro will perform meta-quoting on zero or more forms, then
evaluate each of them:```clojure
(meta/do 1 2 3)
;;=> 3
```Combined with unquoting, this enables you to perform arbitrary computation at
compile time:```clojure
(let [x 2 y 4]
(meta/do ~(+ x y)))
;;=> 6
```Unquoting is syntax aware and provides automatic splicing:
```clojure
(let [args (syntax 2 4)]
(meta/do ~(+ args)))
;;=> 6
```You can use function expressions to defer computation. Note that the unquoted
expression will still be evaluated at compile time:```clojure
(let [x 2 y 4]
(meta/do (fn [] ~(+ x y))))
;=> #
```You can prove this to yourself by using `meta/translate`, which is a cousin
of `macroexpand-all`:```clojure
(let [x 2 y 4]
(meta/translate (fn [] ~(+ x y))))
=> ((fn* ([] 6)))
```Note that the returned value is wrapped in a seq, since Meta-Clojure uniformly
supports multiple expressions with implicit splicing:```clojure
(let [x (syntax 2 3)]
(meta/translate 1 x 4))
;=> (1 2 3 4)
```## Status
- The comments at the bottom of [core.clj](./src/metaclj/core.clj) and
the code in [core_test.clj](./test/metaclj/core_test.clj) form my testbed.
- Many known bugs and incomplete behavior.
- Some special forms not yet supported: `case`, `deftype`, and `reify`.
- No progress yet on [Exotypes][5]
- Use of `clojure.core/eval` is unavoidable at the top level, but it could
be compiled away for more interior forms.
- Maybe someday I'll revive [EClj][4] and build its compiler on Meta-Clojure.## References
- [Multi-stage Programming][1]
- [Terralang][2]
- [MetaOCaml][3]
- [EClj][4]
- [Exotypes][5]## License
Copyright © 2016 Brandon Bloom
Distributed under the Eclipse Public License either version 1.0 or (at
your option) any later version.[1]: https://www.cs.rice.edu/~taha/MSP/
[2]: http://terralang.org/
[3]: http://okmij.org/ftp/ML/MetaOCaml.html
[4]: https://github.com/brandonbloom/eclj
[5]: http://terralang.org/pldi083-devito.pdf