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))

;; 或者

(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),所以我认为这仍然值得考虑。

更新基准:[a rel="nofollow" href="https://jsbench.me/2qjugq4795/2" target="_blank">https://jsbench.me/2qjugq4795/2

0
参考: https://clojure.atlassian.net/browse/CLJS-3071(由thheller汇报)
欢迎使用Clojure问答社区,在这里您可以向Clojure社区的成员提问并获得答案。
...