2024年Clojure调查中分享你的想法!

欢迎!请参阅关于页面以获取更多关于如何使用本站的信息。

0
ClojureScript

示例

(str #js {"toString" (fn [] "hello") "valueOf" (fn [] 42)}) ; => "42"

问题在于ClojureScript使用拼接来将值转换为字符串,而这与重写的valueOf()方法的对象不是很兼容。

JavaScript示例

`
var obj = {

toString: function() { return 'hello'; },
valueOf: function() { return 42; }

};
console.log(String(obj)); => 'hello'
console.log(obj.toString()); => 'hello'
console.log('' + obj); => '42'
`

可能的解决方案可能是使用String()函数。使用toString()在《这个问题》中不会按预期工作:http://dev.clojure.org/jira/browse/CLJS-847

35 个答案

0

评论由:neatonk 发布

toString和valueOf不同步是否有有效的用例?例如。

`(not= (.toString x) (js/String (.valueOf x))`

如果不是,那么这两个方法不同步是否“不正确”?

0

评论由:nbeloglazov 发布

这是一个这样的用例的例子: https://github.com/processing-js/processing-js/blob/master/src/Objects/Char.js
这就是我找到这个错误的方式。

0
by

评论由:neatonk 发布

感谢提供链接。我明白你的意思了。

0
by

评论人:dnolen

使用{{String}}的问题似乎在于对打印产生巨大的性能影响 http://jsperf.com/string-vs-tostring2/6

除非提出一个绝妙的主意,否则这似乎最好在用户代码中解决/规避。

0
by

评论由:nbeloglazov 发布

在字符串和数字上,append执行得更好,但在对象上执行得较差,所以这不是明显的性能影响。如果我大量使用对象并且使用(str)将它们转换为字符串,那么实际上我会因为当前的实现而失去性能。
无论如何,str的当前实现在不遵循toString方法时是不正确的,这正是str函数应该做的。我相信编译器首先应该是正确的,然后再关注性能。

0
by

评论人:dnolen

抱歉再次检查这个问题,我认为真正的问题是我们需要撤销CLJS-801。

0
by

评论人:dnolen

在master中撤销CLJS-801

0
by

评论人:favila

CLJS-801 只处理字符串 。由于 CLJS-847,我们是不是还会遇到字符串 函数 的问题?https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642(另外,如果我们在这里使用 toString,Safari 6.0.5 会崩溃。可能我们需要 {{[o].join('')}}?根据错误的位置,这也可能在 Safari 6.0.5 中出错。)

我们需要非常具体地做到的是,以某种方式获取对象上(用 ECMASCRIPT 术语){{ToString}} 抽象操作的结果(或带有字符串提示的底层 {{ToPrimitive}} 抽象操作)。使用加运算符进行字符串连接

我认为有以下几种选择

  • {{x.toString()}}:因为 CLJS-847 所以不好
  • {{[x].join('')}}:应该可以工作(并且对于 null/undefined 执行正确),但我认为我们应该在 Safari 6.0.5 中进行测试。此外,非常慢。
  • {{String(x)}}
  • {{String.prototype.concat(x)}}
  • {{String.prototype.slice(x, 0)}} {{String.prototype.substring(x, 0)}} {{String.prototype.substr(x, 0)}}
  • 通常情况下使用 {{x.toString()}},但是如果我们检测到将触发 CLJS-847,则使用 {{String(x)}}。(可以在启动时进行专业化。)
0

评论人:dnolen

有证据表明,字符串的高频使用实际上有问题吗?

0

评论人:favila

使用加运算符进行字符串连接会使用未指定的 {{ToPrimitive}} 抽象调用(通常会首先尝试 {{x.valueOf()}},然后是 {{x.toString()}}),然后 {{ToString}} 结果,因此除非我们正在连接原始值,否则这不是选项。

详细说明
ToString http://www.ecma-international.org/ecma-262/5.1/#sec-9.8
ToPrimitive http://www.ecma-international.org/ecma-262/5.1/#sec-9.1
*DefaultValue(ToPrimitive 对象的调用) http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8

0

评论人:dnolen

我并不真正关心规范,只有在野外有关系的时候才关心。如果这不会影响 Safari 6.05,我们就不在乎了。

0

评论人:favila

bq。有证据表明,字符串的高频使用实际上有问题吗?

打开了CLJS-847的人Kevin Neaton,在生产环境中使用了一个补丁,该补丁仅解决了高阶案例。他表示该补丁已为他们解决了此问题。他对str宏情况下的str宏案例没有影响,因为它要么已经应用了CLJS-801使用了''+x(或者在x的接边上没有使用{{[x].join('')}}(尚未在Safari 6.0.5上进行测试,但可能有效)。

因此,如果我们使用str宏中的''+x有问题,那么只要应用CLJS-847,我们使用字符串函数的''+x就会有问题。

我还没有拉取master,但我这里有一个我认为在应用CLJS-847补丁后会失败的测试案例

(def tricky-obj #js {"toString" (fn [] "hello") "valueOf" (fn [] 42)}) (assert (= (apply str tricky-obj) "hello")) ;; 将得到 "42"

0

评论人:favila

bq. 我并不是真的很关心规范,只有当它在野外有关系的时候我才关心。如果这不会影响Safari 6.05,我们就不用担心了。

为了清晰起见,这里有两个问题

CLJS-847:Safari 6.0.5上x.toString()失败。解决方法是''+x(仅在str宏情况下实施)。
CLJS-890:对于定义了valueOf的对象,''+x没有给出预期的结果。期望是调用x.toString(),而不是x.valueOf().toString().解决方案是在str宏中使用数组连接而不是字符串连接,但这没有解决CLJS-847中的''+x解决方法。

更糟糕的是,看起来Safari上的toString()错误可能仅在特定的JIT级别上触发!

0

评论人:favila

bq. 解决方案是''+x(仅在str宏情况下实施)。

我的意思是“解决方案是''+x(仅在str strong函数的情况下实施)。"

0

评论由:nbeloglazov 发布

这个错误现在可以重新打开吗?如果我的理解正确,修复应该影响https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642,但这段代码仍然存在于HEAD中。

...