2024 年 Clojure 调查! 分享您的想法。

欢迎!请参阅 关于页面 了解更多关于此功能的信息。

0 投票
ClojureScript

当前在定义实现 {{clojure.core/IFn}} 协议的类型时,不仅生成了一个协议函数,还生成了一个重复整个代码的 {{.call}} 方法,而不是调用生成的协议函数进行分发。

`
(deftype InvokeTest [a b]
IFn
(-invoke [_]

(+ a b)))

`

cljs.user.InvokeTest.prototype.cljs$core$IFn$_invoke$arity$0 = function() { var self__ = this; var _ = this; return self__.a + self__.b; };

{{.call}} 重复所有代码,而不是调用的 this.cljs$core$IFn$_invoke$arity$<n>。多个参数个数会重复每个参数个数的代码。

cljs.user.InvokeTest.prototype.call = function(self__) { var self__ = this; var self____$1 = this; var _ = self____$1; return self__.a + self__.b; };

应该是这样的

`
cljs.user.InvokeTest.prototype.call = function(self__) {
switch(arguments.length) {

case 0:
  return this.cljs$core$IFn$_invoke$arity$0();
...
default:
  throw new Error("Invalid arity: " + arguments.length);

}
};
`

8 回答

0 投票

评论来自:thheller

注意,在 {{:advanced}} 中,Closure 不会删除 {{.call}} 函数。

伪名称输出

`
$JSCompiler_prototypeAlias$$ = $cljs$core$Keyword$$.prototype;
$JSCompiler_prototypeAlias$$.call = function() {
var $G41215$$ = null;
$G
41215$$ = function($G__41215$$, $coll$jscomp$188$$, $not_found$jscomp$10$$) {

switch(arguments.length) {
  case 2:
    return $cljs$core$get$$.$cljs$core$IFn$_invoke$arity$2$($coll$jscomp$188$$, this);
  case 3:
    return $cljs$core$get$$.$cljs$core$IFn$_invoke$arity$3$($coll$jscomp$188$$, this, $not_found$jscomp$10$$);
}
throw Error("Invalid arity: " + (arguments.length - 1));

};
$G__41215$$.$cljs$core$IFn$_invoke$arity$2$ = function($G__41215$$, $coll$jscomp$186$$) {

return $cljs$core$get$$.$cljs$core$IFn$_invoke$arity$2$($coll$jscomp$186$$, this);

};
$G__41215$$.$cljs$core$IFn$_invoke$arity$3$ = function($G__41215$$, $coll$jscomp$187$$, $not_found$jscomp$9$$) {

return $cljs$core$get$$.$cljs$core$IFn$_invoke$arity$3$($coll$jscomp$187$$, this, $not_found$jscomp$9$$);

};
返回 $G__41215$$;
}();
$JSCompiler_prototypeAlias$$.$cljs$core$IFn$_invoke$arity$1$ = function($coll$jscomp$189$$) {
返回 $cljs$core$get$$.$cljs$core$IFn$_invoke$arity$2$($coll$jscomp$189$$, this);
};
$JSCompiler_prototypeAlias$$.$cljs$core$IFn$_invoke$arity$2$ = function($coll$jscomp$190$$, $not_found$jscomp$11$$) {
返回 $cljs$core$get$$.$cljs$core$IFn$_invoke$arity$3$($coll$jscomp$190$$, this, $not_found$jscomp$11$$);
};
`

0 投票

评论来自:dnolen

在这里留下一个备注,上面的例子看起来很像是正在建议的内容,但正如托马斯所指出,它是调用到get

0 投票
by

评论来自:thheller

附加的补丁按计划调整了生成的{{.call}}函数。

现在生成的代码更加紧凑且不重复。

`
$JSCompiler_prototypeAlias$$ = $cljs$core$Keyword$$.prototype;
$JSCompiler_prototypeAlias$$.call = function($unused60227auto__$jscomp$3$$) {
switch(arguments.length - 1) {

case 0:
  return this.$cljs$core$IFn$_invoke$arity$0$();
case 1:
  return this.$cljs$core$IFn$_invoke$arity$1$(arguments[1]);
case 2:
  return this.$cljs$core$IFn$_invoke$arity$2$(arguments[1], arguments[2]);
default:
  throw Error(["Invalid arity: ", $cljs$core$str$$.$cljs$core$IFn$_invoke$arity$1$(arguments.length - 1)].join(""));

}
};
$JSCompiler_prototypeAlias$$.$cljs$core$IFn$_invoke$arity$1$ = function($coll$jscomp$183$$) {
return $cljs$core$get$$.$cljs$core$IFn$_invoke$arity$2$($coll$jscomp$183$$, this);
};
$JSCompiler_prototypeAlias$$.$cljs$core$IFn$_invoke$arity$2$ = function($coll$jscomp$184$$, $not_found$jscomp$7$$) {
return $cljs$core$get$$.$cljs$core$IFn$_invoke$arity$3$($coll$jscomp$184$$, this, $not_found$jscomp$7$$);
};
`

我不确定为什么自我托管测试失败。

0 投票
by

评论来自:thheller

这不是什么大问题,但在我的:advanced测试构建中,{{cljs.core}}代码大小从168.8KB降至163.2KB(非gzip),因此它确实减少了生成的总体代码量。

0 投票
by

评论来自:thheller

更新的补丁修复了使用最大固定参数的程序错误,假设所有较低参数都始终存在。

还修复了所有自我托管问题和测试似乎现在运行良好。

0 投票
by

评论来自:thheller

更正:当前的测试CLJS-2133失败。

ERROR in (test-cljs-2133) (错误:NaN:1) 未在断言中捕获到的异常。预期:nil 实际:#object[Error 错误:arity无效: 1]

我可以调整补丁以允许可变参数的行为,但由于它从1.9.660版本开始官方未支持并生成警告,可能需要完全移除支持?

0 投票
by

评论者:mfikes

从1.9.660开始,我们通过CLJS-2134有一个诊断工具。

Slack上的David的评论

"我认为1.9.660可能已经足够长,不必过于关心它了。"
我对这个补丁没问题,我们看看反馈如何

也许我们可以在这次补丁中移除/cljs-2133增加的单元测试?

0 投票
参考:https://clojure.atlassian.net/browse/CLJS-3003(by thheller报告)
...