Clojure 在(def+;-)之后,有没有办法拥有+;运算符“加法”而不是“减法”?

Clojure 在(def+;-)之后,有没有办法拥有+;运算符“加法”而不是“减法”?,clojure,Clojure,我在学Clojure。为了看看我是否可以做一些比Python更奇怪的事情,我做了: > (+ 2 2) 4 > (def + -) #'sandbox6693/+ > (+ 2 2) 0 这令人惊讶地奏效了,但是我不知道如何在上面的定义之后获得+来再次添加。有办法吗?我不认为您正在删除clojure.core函数+,只是将其隐藏在名称空间中 您可以通过将+重新命名为clojure.core中的函数,并引用它(包括名称空间),将其取回: user=> (def + -)

我在学Clojure。为了看看我是否可以做一些比Python更奇怪的事情,我做了:

> (+ 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