Share your thoughts in the 2020 Clojure Community Survey!

Welcome! Please see the About page for a little more info on how this works.

0 votes
in ClojureScript by

I have this macro:

(defmacro log
  "Take any number of expressions. For each expression print 'expr=value' on
  js/console. For self-evaluating expressions (eg. keywords, strings) omit
  the 'expr=' part. Each expression is only evaluated once."
  [& exprs]
  `(let [evaluated# (list ~@exprs)
         lst# (map #(if (= %1 %2)
                      (list %2)
                      (list %1 %2))
                   '~exprs
                   evaluated#)]
     (.log js/console lst#)))

It evaluates like this:

background:cljs.user=> (log :a (+ 1 2) js/console)
;; => nil
;; js/console output => ((:a) (▶(…) 3) (js/console ▶#js {…}))

The macroexpansion looks like this:

background:cljs.user=> (macroexpand '(log :a (+ 1 2) js/console))
(let*
 [evaluated__55571__auto__
  (clojure.core/list :a (+ 1 2) js/console)
  lst__55572__auto__
  (clojure.core/map
   (fn*
    [p1__55569__55573__auto__ p2__55570__55574__auto__]
    (if
     (clojure.core/= p1__55569__55573__auto__ p2__55570__55574__auto__)
     (clojure.core/list p2__55570__55574__auto__)
     (clojure.core/list
      p1__55569__55573__auto__
      p2__55570__55574__auto__)))
   '(:a (+ 1 2) js/console)
   evaluated__55571__auto__)] 
 (.log js/console lst__55572__auto__))

I want to eliminate the superfluous parentheses in the output. How do I splice the elements of lst# into the .log macro? I can't use apply because .log is not a function and (.log js/console ~@lst#) doesn't work.

I also want to be able to expand the objects in the result on the console, so I can't convert everything to strings and give one big string to .log.

1 Answer

+2 votes
by
selected by
 
Best answer

Try using JavaScript's own apply method, e.g.

(.apply js/console.log js/console lst#)

...