Clojure 在(def+;-)之后,有没有办法拥有+;运算符“加法”而不是“减法”?
我在学Clojure。为了看看我是否可以做一些比Python更奇怪的事情,我做了:Clojure 在(def+;-)之后,有没有办法拥有+;运算符“加法”而不是“减法”?,clojure,Clojure,我在学Clojure。为了看看我是否可以做一些比Python更奇怪的事情,我做了: > (+ 2 2) 4 > (def + -) #'sandbox6693/+ > (+ 2 2) 0 这令人惊讶地奏效了,但是我不知道如何在上面的定义之后获得+来再次添加。有办法吗?我不认为您正在删除clojure.core函数+,只是将其隐藏在名称空间中 您可以通过将+重新命名为clojure.core中的函数,并引用它(包括名称空间),将其取回: user=> (def + -)
> (+ 2 2)
4
> (def + -)
#'sandbox6693/+
> (+ 2 2)
0
这令人惊讶地奏效了,但是我不知道如何在上面的定义之后获得+来再次添加。有办法吗?我不认为您正在删除
clojure.core
函数+
,只是将其隐藏在名称空间中
您可以通过将+
重新命名为clojure.core
中的函数,并引用它(包括名称空间),将其取回:
user=> (def + -)
#'user/+
user=> (+ 2 2)
0
user=> (def + clojure.core/+)
#'user/+
user=> (+ 2 2)
4
但是。。。。为什么 正如@Russell所说,您只是在用
user/+
跟踪clojure.core/+
在试用clojure时,我要做的是建立一些本地绑定(再次用+
隐藏核心+
,但要将更改保持在绑定范围内,而不是搞得一团糟):
但一般来说,有一些特殊的方法可以实现您想要的功能(要更改var的值,请在更改var的范围内执行一些代码,然后自动恢复其值):
第一种方法是使用绑定
(),问题是它只适用于特殊的动态
变量,因此它实际上不适用于您的情况,因为+
不是动态的
第二种方法是将与redefs
()结合使用,这更接近您的需要,但有一个问题:
user> (with-redefs [+ -]
(+ 1))
-1 ;; as expected
user> (with-redefs [+ -]
(+ 1 2 3))
6 ;; unexpected!
第二个示例失败,因为当有多个参数传递给编译器时,编译器内联了+
函数,并将其替换为add
函数调用)
此外,出于纯粹的教育目的,您可以制作一个宏,该宏通常会重新定义您需要的所有内容,保存旧值,并在块计算后恢复它:
user> (defmacro redefine [old new & body]
`(let [v# ~old]
(def ~old ~new)
(let [res# (do ~@body)]
(def ~old v#)
res#)))
#'user/redefine
user> (redefine
+ -
(+ 1 2 3))
-4
user> (+ 1 2 3)
6
user> #'+
#'user/+
user> (redefine
+ *
(+ 1 2 4))
8
user> (redefine
+ *
(+ 1 2 4))
8
user> (+ 1 2 4)
7
对于add函数的编译器内联,这是一个有趣的问题!虽然这是一个很好的答案,但我强烈建议您,如果您是Clojure的新手,@Atonal。。。很少有需要宏的情况,但使用宏会带来代码可理解性方面的不小成本,而且初学者/中间用户经常过度使用宏。@Russell我同意,宏会增加一些复杂性,有时甚至很难理解,特别是对于初学者,但另一方面,这是一个功能强大得出奇的工具,它使Lisp脱颖而出,所以我只想说“响应地使用”而不是“避免”)
user> (defmacro redefine [old new & body]
`(let [v# ~old]
(def ~old ~new)
(let [res# (do ~@body)]
(def ~old v#)
res#)))
#'user/redefine
user> (redefine
+ -
(+ 1 2 3))
-4
user> (+ 1 2 3)
6
user> #'+
#'user/+
user> (redefine
+ *
(+ 1 2 4))
8
user> (redefine
+ *
(+ 1 2 4))
8
user> (+ 1 2 4)
7