• Stars
    star
    163
  • Rank 231,141 (Top 5 %)
  • Language
    Clojure
  • License
    Eclipse Public Li...
  • Created about 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A set of three macros to ease writing `*.cljc` supporting Clojure, Clojurescript and self-hosted Clojurescript.

Macrovich

Because any macros problem can be solved by another level of macros, Macrovich is a set of four macros to ease writing *.cljc supporting Clojure, Clojurescript and self-hosted Clojurescript. (Especially when porting Clojure codebases where macros are not segregated.)

Excerpt from Being John Macrovich script:

Girl Macrovich
Macrovich Macrovich Macrovich Macrovich...
(Macrovich looks confused. The Macrovich waiter approaches, pen and pad in hand, ready to take their orders.)
Waiter Macrovich
Macrovich Macrovich Macrovich?
Girl Macrovich
Macrovich Macrovich Macrovich Macrovich.
Waiter Macrovich
Macrovich Macrovich. (Turning to Macrovich) Macrovich?

Usage

Clojurescript >= 1.9.293 is required. This means Planck 2.0.0 or later is required. Lumo 1.0.0 is ok.

Add [net.cgrand/macrovich "0.2.1"] to your dependencies.

Macrovich exposes four macros:

  • macros/deftime and macros/usetime to clearly demarcate regions of code that should be run in the macro-definition stage or in the macro-usage stage. (In Clojure there's no distinction; in pure Clojurescript it's easy: just wrap the first stage in #?(:clj ...) and the latter one in #?(:cljs ...); in self-hosted Clojurescript it's messy or everything gets evaluated twice; supporting the three at the same time is Macrovich's raison d'être.)
  • macros/case is a macro to use instead of reader conditionals in macros or macros-supporting fns. This solves a problem with regular Clojurescript where macros are Clojure code and thus are read by taking the :clj branch of conditionals. So macros/case is like reader conditionals except the branch is picked at expansion time and not at definition time.
  • macros/replace is a macro to avoid repeating similar reader conditionals, see https://github.com/cgrand/xforms/blob/d4f0280bb50d8cc53c3a5dfe24b17fe7701b4e43/src/net/cgrand/xforms.cljc#L276 for an example.

Sample

Below is a sample being/john.cljc file:

(ns being.john
  #?(:clj
     (:require [net.cgrand.macrovich :as macros])
     :cljs
     (:require-macros [net.cgrand.macrovich :as macros]
        [being.john :refer [add]]))) ; cljs must self refer macros

(macros/deftime
  ; anything inside a deftime block will only appear at the macro compilation stage.

  (defmacro add
    [a b]
    `(+ ~a ~b)))

(macros/usetime
  ; anything inside a usetime block will not appear at the macro compilation stage.

  (defn sum
    [a b]
    (add a b)))
    
; anything outside these block is always visible as usual

case allows to select which form to emit in a macro based on the target language rather than the macro language. Consider these two macros:

(defmacro broken []
  #?(:clj "clojure" :cljs "clojurescript"))

(defmacro correct []
  (macros/case :clj "clojure" :cljs "clojurescript"))

; or
(defmacro correct []
  `(macros/case :clj "clojure" :cljs "clojurescript")) ; this works too, so no need to unquote in the middle of a syntax quotation and mess with gensyms

In regular (Clojure-hosted) Clojurescript (broken) expands to "clojure" while (correct) expands to "clojurescript".

Example

The xforms lib has been converted to cljc:

License

Copyright © 2016-2017 Christophe Grand

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

More Repositories

1

enlive

a selector-based (à la CSS) templating and transformation system for Clojure
Clojure
1,619
star
2

xforms

Extra transducers and reducing fns for Clojure(script)
Clojure
573
star
3

moustache

a micro web framework/internal DSL to wire Ring handlers and middlewares
Clojure
261
star
4

enliven

Enlive next: faster, better, broader
Clojure
243
star
5

seqexp

Regexp for sequences!
Clojure
241
star
6

parsley

a DSL for creating total and truly incremental parsers in Clojure
Clojure
200
star
7

sjacket

Structural code transformations for the masses.
Clojure
114
star
8

megaref

STM ref types that allow for more concurrency on associative values.
Clojure
95
star
9

spreadmap

Evil project to turn excel spreadsheets in persistent reactive structures.
Clojure
89
star
10

regex

a regex DSL for those who prefer verbose composable regexes to terse ones
Clojure
88
star
11

poucet

trace as data for Clojure/JVM
Clojure
86
star
12

confluent-map

A persistent confluent map for Clojure
Java
39
star
13

packed-printer

Compact pretty printer
Clojure
37
star
14

sqrel

The SQL library that won't drive you nuts.
Clojure
37
star
15

utils

useful functions and extensible macros
Clojure
36
star
16

indexed-set

A set implementation which supports unicity constraints and maintains summaries (indexes).
Clojure
31
star
17

replay

Instant test suites from repl transcript.
Clojure
26
star
18

cljs-js-repl

Upgradable self hosted clojurescript repl
Clojure
21
star
19

parsnip

parsley is dead, long live parsnip!
Clojure
17
star
20

boring

A tunnel-boring library
Clojure
11
star
21

enlivez

Clojure
8
star
22

dynvars

dynamic bindings in callback hell
Clojure
5
star
23

sandbox

expeiments, works in progress etc.
Clojure
4
star
24

advent2017

Clojure
2
star
25

trainings.geneva.2012

Ressources issues des formations Clojure données du 13 au 15 mai 2012
Clojure
2
star
26

berlin-tron

Clojure
1
star