2024年Clojure状态调查!分享你的想法。

欢迎!请参阅关于页面,了解更多关于它是如何工作的信息。

0
ClojureScript
目前没有办法让分析器/编译器直接调用一个函数,即使我们知道某东西只是一种函数,永远不会是IFn/可变参数/多版本形式的。


(ns test.invoke)

(defn call-me [some-fn arg]
  (some-fn arg))

(call-me #(js/console.log %) "foo")


产生


test.invoke.call_me = (function test$invoke$call_me(some_fn,arg){
return (some_fn.cljs$core$IFn$_invoke$arity$1 ? some_fn.cljs$core$IFn$_invoke$arity$1(arg) : some_fn.call(null,arg));
});
test.invoke.call_me((function (p1__91346_SHARP_){
return console.log(p1__91346_SHARP_);
}),"foo");


正如你所看到的,始终存在{{some_fn.cljs$core$IFn$_invoke$arity$1}}属性测试,这总会失败并运行{{.call}}。这对于可能接受{{cljs.core/IFn}}实现的函数是有意义的,但有很多情况只会接收纯函数(例如,JS互操作),应该可以通过某种注释来告诉编译器,这样它可以发出更优化的{{some_fn(arg)}}代码。{{:advanced}}编译也不处理这个问题。

我在这里创建了一个基准测试套件,显示prop/call样式调用始终比30-40%慢,我希望在一些罕见的情况下进行优化。

见:https://jsbench.me/2qjugq4795/1

我们可以通过现有的{{^js}}注释来处理这个问题,或者创建一个新的像{{^fn}}这样的东西。


(defn call-me [^js some-fn arg]
  (some-fn arg))

;; and/or

(defn call-me [^fn some-fn arg]
  (some-fn arg))

(defn call-me [some-fn arg]
  ^fn (some-fn arg))



这是一个与{{^not-native}}类似的优化,应该谨慎且少量使用。

2 答案

0

评论者:thheller

我忘记设置{{:fn-invoke-direct}},这将产生更优化的代码,但仍有3-10%的开销(Chrome,Firefox)所以在我看来这仍然值得考虑。

更新基准:https://jsbench.me/2qjugq4795/2

0
参考资料:https://clojure.atlassian.net/browse/CLJS-3071(由thheller报告)
...