4

In clojureScript the following multi-arity function

(defn sum [& xs] (reduce + xs))

can be either called via (sum 4 6 9) or by the use of (apply sum [4 6 9]) which yields the same result.

How can this be done with a native JavaScript function, such as: console.log.

(apply js/console.log [1 2 3])

This, yields the following error:

#object[TypeError TypeError: 'log' called on an object that does not implement interface Console.]
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
Anton Harald
  • 5,772
  • 4
  • 27
  • 61
  • I'm not sure about clojureScript, but in JS you need `console.log.apply(console, […])` to make it work (though it's browser-specific) – Bergi Aug 20 '16 at 17:07
  • 1
    hmm... this is interesting. In planck (osx clojurescript repl) I tried this out and it worked fine. `(apply js/console.log [1 2 3])` and `(js/console.log 1 2 3)` both print `1` and return `nil` – Paul Gowder Aug 22 '16 at 02:10
  • 1
    this has gotta be some browser-specific thing. I just fired up a minimal figwheel project (from this template: https://github.com/bhauman/figwheel-template ) and sent `(apply js/console.log [1 2 3])` to the browser from the figwheel repl; it logged `1 2 3` --- I'm using a current version of Chrome, what are you using? – Paul Gowder Aug 22 '16 at 02:19
  • just to make sure this isn't an implementation difference on the javascript side in whatever environment you're using, what happens when you try `(apply js/Math.sqrt [25])`? It should return 5 without a problem. – Paul Gowder Aug 22 '16 at 02:35

3 Answers3

5

Some browsers always assuming the this is certain object, you can use .bind in js for temporal fix.

; you can use .bind on any function
(def d (.bind (.-log js/console) js/console))
(def ms ["aaa" "bbb" "barbarbar"])
(mapv d ms)

Related questions

What does this statement do? console.log.bind(console)

Why do js functions fail when I assign them to a local variable?

Community
  • 1
  • 1
ka yu Lai
  • 571
  • 3
  • 13
2

There might be an error in your code. apply works totally fine out of the box for JS functions:

cljs.user=> (apply js/Math.sqrt [25])
5

You can test it with this online REPL and I also tested it in my local project -- no problems so far.

cljs.user=> (apply js/console.log [1 2 3])
nil

also prints the output in the normal JS console as expected.

n2o
  • 6,175
  • 3
  • 28
  • 46
0

Using js/a.b only works when a is global in your environment. Either way, I find this much cleaner:

(apply (.-log js/console) [1 2 3])

Note: with member functions, don't forget the first argument is this.

MasterMastic
  • 20,711
  • 12
  • 68
  • 90