为什么我无法绑定+在 Clojure 中?
谁能解释为什么我可以重新绑定列表但不能重新绑定+?
(binding [list vector]
(list 1 3))
(binding [list +]
(list 1 3))
(binding [+ list]
(+ 1 3))
我想重新绑定 + 这样我就可以进行部分评估。
Can anyone explain why I can rebind list but not +?
(binding [list vector]
(list 1 3))
(binding [list +]
(list 1 3))
(binding [+ list]
(+ 1 3))
I'd like to rebind + so I can do partial evaluation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
至少在 Clojure 1.1.0 中,为了提高性能,带有两个参数的
+
被内联。你的绑定发生得太晚了。随着更多的争论,它的工作方式会有所不同。一种解决方法是使用您自己的函数创建您自己的命名空间和影子
clojure.core/+
。请注意,在 Clojure 1.2.0 的当前快照中,内联似乎更加频繁地发生。
最明智的做法可能是使用
+
以外的函数名称,例如add
,以避免混淆。In Clojure 1.1.0 at least,
+
with two arguments is inlined for performance. Your binding happens too late. With more arguments it works differently.One workaround is to make your own namespace and shadow
clojure.core/+
with your own function.Note that inlining appears to happen even more aggressively in the current snapshot of Clojure 1.2.0.
It may be wisest to use a function name other than
+
, e.g.add
, to avoid confusion.快速解决方法:使用let而不是绑定,这对你来说很好:
稍微(不完整)深入探究一下原因:
看看 + 的源代码函数:
请注意,有多个内联函数定义用于不同数量的参数。如果您尝试重新绑定 0 或 1 个参数定义,它会正常工作:
现在,这对于 2 个参数的情况绝对不起作用(正如您所发现的)。我不太能把这些点联系起来,但是. (特殊形式)让我怀疑结合绑定是一个宏,而 let 是一种特殊形式......
专门调用 arity 2 的元数据也似乎很可疑。
Quick workaround: use let instead of binding and this will work for you just fine:
A little (incomplete) digging into the reason:
Take a look at the source for the + function:
Notice that there are several inline function definitions for different numbers of arguments. If you try to rebind the 0 or 1 arity definitions, it works just fine:
Now, this definitely doesn't work (as you discovered) for the 2-argument case. I'm not quite connecting the dots, but the . (special form) makes me suspicious combined with binding being a macro whereas let is a special form...
The metadata specially calling out arity 2 also seems suspicious.