#?@ reader conditional splicing

syntaxsince v0.0-3190 in clojureEdit

Like #? reader conditional, except the result is spliced (i.e. [a b] => a b)

  • #?@(:clj [...] :cljs [...])


(Only allowed in .cljc files or the REPL)

Like #? reader conditional, except:

  • each conditional value must be a sequence,
  • the selected sequence is spliced into the parent form,
  • and it must have a parent form to be spliced into (not top level).

(def #?@(:cljs [foo 1]) is read as (def foo 1).


'(def #?@(:cljs [a 1]
          :clj  [b 2]))
;;=> (def a 1)

See Also:

Reader code @ tools.reader:src/main/clojure/clojure/tools/reader.clj
(defn- read-cond
  [rdr _ opts pending-forms]
  (when (not (and opts (#{:allow :preserve} (:read-cond opts))))
    (throw (RuntimeException. "Conditional read not allowed")))
  (if-let [ch (read-char rdr)]
    (let [splicing (= ch \@)
          ch (if splicing (read-char rdr) ch)]
      (when splicing
        (when-not *read-delim*
          (err/reader-error rdr "cond-splice not in list")))
      (if-let [ch (if (whitespace? ch) (read-past whitespace? rdr) ch)]
        (if (not= ch \()
          (throw (RuntimeException. "read-cond body must be a list"))
          (binding [*suppress-read* (or *suppress-read* (= :preserve (:read-cond opts)))]
            (if *suppress-read*
              (reader-conditional (read-list rdr ch opts pending-forms) splicing)
              (read-cond-delimited rdr splicing opts pending-forms))))
        (err/throw-eof-in-character rdr)))
    (err/throw-eof-in-character rdr)))

Reader table @ tools.reader:src/main/clojure/clojure/tools/reader.clj
(defn- dispatch-macros [ch]
  (case ch
    \^ read-meta                ;deprecated
    \' (wrapping-reader 'var)
    \( read-fn
    \= read-eval
    \{ read-set
    \< (throwing-reader "Unreadable form")
    \" read-regex
    \! read-comment
    \_ read-discard
    \? read-cond
    \: read-namespaced-map
    \# read-symbolic-value