在 Clojurescript 中,如何将集合的元素作为参数传递给变量 arity Javascript 函数?

In Clojurescript, how do I pass a collection's elements as arguments to a variable arity Javascript function?

写这篇文章是为了安慰我所期望的方式:

(.log js/console "hi" "there")

输出为

hi there

然而,这只会向控制台写入一团乱麻:

(defn log-it [& args] (.log js/console args))
(log-it "hello" "there")

输出为:

c…s.c…e.IndexedSeq {arr: Array[2], i: 0, meta: null, cljs$lang$protocol_mask$partition0$: 166592766, cljs$lang$protocol_mask$partition1$: 8192}

这也行不通:

(apply .log js/console ["hi" "there"])

有没有办法将向量的元素传递给 .log 函数? 我是否必须编写一个宏来将向量连接到 '(.log js/console)

这里的问题是您试图记录 args 的值(这是一个 Clojure IndexedSeq),而不是将 seq 中的值作为单独的参数传递。在这种情况下,您需要使用 apply(或将该序列转换为本机数据结构)。

如果您查看 the signature for apply.

,您的另一个示例不起作用的原因应该会变得清楚
(apply f args)

它期望第一个参数是您要调用的函数,但在这里,第一个参数是 .log

(apply .log js/console ["hi" "there"])

请记住,.log js/console 是在 console 上调用 log 方法的语法。相反,我们想要获得对 console.log 函数的引用。

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

我们使用 .-log 来读取 .log 属性,而不是将其作为方法调用。然后我们将它与我们的 args 序列一起传递。

因此,您可以将原始函数定义为:

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

或者如果你想变得更聪明一点。

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