我开始学习clojure以便原谅noob问题 我尝试实现以下功能
伪代码:
function(x y) {
if (x != oldX)
dosomething(y);
oldX = x;
}
oldX
是全局变量
我怎样才能正确地做到这种方式呢?
我写了一些东西,但这是否正确?
(defn rec [x y]
(if (not= x oldX)
(println "y"))
(def oldX x))
答案 0 :(得分:5)
defs
应该只是顶级。 (def oldX (atom nil))
和(reset! oldX x)
更正确。
答案 1 :(得分:3)
Clojure是一种函数式编程语言。这是一种与其他流行的编程语言(如Python)不同的范例。你似乎没有想到功能; - )
Clojure-way不会在这种情况下使用变量。只需使用函数解决它,或者,如果确实有必要,请使用atoms
或ref
s,具体取决于您的需要。
可以在函数中修改atom
或ref
以存储旧结果 - 这可能是您正在寻找的解决方案。
但是对于大多数情况,存在一个更简单的解决方案,而不需要像oldX
这样的变量 - 这就是功能语言的好处。
您的代码
(defn rec [x y]
(if (not= x oldX)
(println "y"))
(def oldX x))
正如@cgrand已经说过,def
只能在第一级使用。
您使用if
,但只定义true
个案。如果您只检查,如果某个陈述为真,那么您可以使用when
。
最后一行在函数oldX
的范围内定义了新的rec
。这是一个 new 变量,而不是具有新值的旧变量,在活动命名空间中(感谢@ user1571406)。
答案 2 :(得分:0)
我认为你正在寻找的是这样的。我已经尝试将您的var名称保留为原始名称,因此更容易看出差异。
atom
存储oldX
compare-and-set!
确定您是否更改了原子(dosomething y)
注意:这有点像swap!
,除了swap!
返回交换的值,而不是您对swap!
的调用是否改变了价值,所以在这里不太有用。
这样的事情:
(defn dosomething [y]
;; does something, presumably with y...
)
(defonce x-atom (atom nil))
(defn swap-x
"swaps x-atom for new x, calls (dosomething ...) with y if successful"
[x y]
(let [oldX @x-atom] ; get the cur value of x
(when (not= oldX x)
(when (compare-and-set! x-atom oldX x)
(dosomething y))
如果compare-and-set!
失败,则意味着其他一些线程已经修改了原子,因为你得到了它的值。如果你需要处理这种情况,答案会有所不同。您可以使用swap!
或loop+recur
。如果您不熟悉,swap!
有点像compare-and-set!
,会在失败时重复出现。