js/console.log in ClojureScript

若如初见. 提交于 2019-12-21 04:04:06

问题


I want to implement a function with ClojureScript to simplify js/console.log like this:

  (defn log [& args]
      (apply js/console.log args))

Calling it : (log "foo" "bar") throws: TypeError: Illegal invocation

but this works : (js/console.log "foo" "bar")

What is the problem ?


回答1:


js/something is for accessing a js object, but you shouldnt nest dots after that, since it is not clojure compatible syntax and it was going to be removed. In older versions of the compiler (2138) your code works, but it is possible that it has been deprecated in newer versions of the compiler. Which version are you using?

The correct way would be using straightforward js interop like this: [Caveat: see comment below from David Nolen, ClojureScript lead developer]

(defn log [& args] (apply (.-log js/console) args))

And even shorter, since console.log is already variadic (just make an alias):

(def log (.-log js/console))



回答2:


You can also just use println if you first put this at top of your file: (enable-console-print!).




回答3:


And pprint has been ported:

:require [cljs.pprint :refer [pprint]]



回答4:


I found the actual answer

(.apply (.-log js/console) js/console (clj->js args))



回答5:


Here is a working code for your function (tested with [org.clojure/clojurescript "1.7.228"]):

; working
(defn log [& args]
  (.apply js/console.log js/console (to-array args)))

; not working
; (defn log [& args] (apply (.-log js/console) args))
; (defn log [& args] (apply js/console.log args))
; (def log js/console.log)

Here is an article that describes why (apply...) is not playing well with JS functions. http://clojurescriptmadeeasy.com/blog/how-to-apply-with-the-console-api.html




回答6:


With console.log makes sense to use a macro instead of a function. If you implement log as a function all the messages will be logged with the line number of where your log function is defined.

A macro solves this problem by generating inline code during compilation, it's important to understand that macros run at compile time.

Define this macro in macros.cljc:

(ns test.macros)

(defmacro log
  [& msgs]
  `(.log js/console ~@msgs))
  • `: is like ' or quote but:
    • Symbols are auto-resolved to include their namespace, preventing ambiguous symbols at the time of evaluation.
    • Evaluated forms can be inserted using ~ or unquote, as i did for msgs adding @ to unpack multiple arguments: ~@msgs. More info about syntax quote.

Then call it from core.cljs:

(ns test.core
  (:require-macros [test.macros :refer [log]]))

(log "foo" "bar")


来源:https://stackoverflow.com/questions/24239144/js-console-log-in-clojurescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!