Liking cljdoc? Tell your friends :D

Compile-time namespaces

Macros run in squint's compiler (SCI on Node.js) such that the runtime (browser) can remain minimal. Previously it was cumbersome to make an existing .cljc namespace compatible with squint, if not all of the code of that namespace could be evaluated through SCI. To solve this problem, a namespace can opt in to loading only its squint compile-time parts using the special :squint/compile-time annotation:

(ns my.lib
  {:squint/compile-time true} ;; annotate this namespace for explicit compile time parts
  (:require [clojure.string :as str]))

;; a top-level defmacro is compile-time automatically
(defmacro shout [x]
  `(str/upper-case ~x))

;; mark any other compile-time form (an expansion helper, a defmethod)
^:squint/compile-time
(defn slugify [s]
  (str/replace (str/lower-case s) " " "-"))

(defmacro const-slug [s]
  (slugify s))

;; unmarked forms are runtime only and never evaluated in SCI
(defn runtime-thing [x]
  (inc x))

With the :squint/compile-time flag in the namespace's metadata, squint loads only the defmacros and explicitly marked forms into SCI. The rest of the file is compiled to JS as usual, with the compile-time forms stripped.

Compile-time forms may live inside a #?(:clj ...) branch, the place a .cljc namespace usually keeps them for JVM-hosted ClojureScript. Since the :clj branch often contains JVM-only code (a macro may read JVM config at expansion time), a form there needs the explicit marker:

#?(:clj
   ^:squint/compile-time
   (defmacro shout [x]
     `(str/upper-case ~x)))

Unmarked #?(:clj ...) code (JVM interop, registrations, macros with JVM-only bodies) is never evaluated by squint.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close