上一个函数输入参数正确存储
previous function input parameter correct storing
我开始学习clojure所以请原谅菜鸟问题
我尝试实现以下功能
伪代码:
function(x y) {
if (x != oldX)
dosomething(y);
oldX = x;
}
oldX
是全局变量
我怎样才能以 clojure 的方式正确地做到这一点?
我写了一些东西,但这种方式是否正确?
(defn rec [x y]
(if (not= x oldX)
(println "y"))
(def oldX x))
defs
应该只是顶级。 (def oldX (atom nil))
和 (reset! oldX x)
更正确。
Clojure 是一种函数式编程语言。这是一种不同于其他流行编程语言(如 Python)中使用的范例。您似乎没有考虑功能性 ;-)
在这种情况下,Clojure 的方式是不使用变量。用函数解决就行了,或者,如果真的有必要,使用atoms
或ref
s,这取决于你需要什么。
可以在函数中修改 atom
或 ref
以存储旧结果 - 这可能是您正在寻找的解决方案。
但是对于大多数情况,存在一个更简单的解决方案,不需要像 oldX
这样的变量——这就是函数式语言的好处。
您的代码
(defn rec [x y]
(if (not= x oldX)
(println "y"))
(def oldX x))
正如@cgrand 所说,def
只应在第一层使用。
您使用 if
,但您只定义了 true
情况。如果你只检查,如果某个陈述为真,那么你可以使用 when
.
最后一行在函数rec
的范围内定义了一个新的oldX
。这是活动命名空间中的 new 变量,而不是具有新值的旧变量(感谢 @user1571406)。
我认为您正在寻找的是这样的东西。我已尝试将您的 var 名称保留为原始名称,因此更容易看出差异。
- 使用
atom
存储oldX
- 使用
compare-and-set!
来确定你是否已经改变了原子
- 如果您更改了原子,请致电您的
(dosomething y)
注意: 这有点像 swap!
,除了 swap!
returns 换入的值,而不是你的调用 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!
,它会在失败时重现。
我开始学习clojure所以请原谅菜鸟问题 我尝试实现以下功能
伪代码:
function(x y) {
if (x != oldX)
dosomething(y);
oldX = x;
}
oldX
是全局变量
我怎样才能以 clojure 的方式正确地做到这一点?
我写了一些东西,但这种方式是否正确?
(defn rec [x y]
(if (not= x oldX)
(println "y"))
(def oldX x))
defs
应该只是顶级。 (def oldX (atom nil))
和 (reset! oldX x)
更正确。
Clojure 是一种函数式编程语言。这是一种不同于其他流行编程语言(如 Python)中使用的范例。您似乎没有考虑功能性 ;-)
在这种情况下,Clojure 的方式是不使用变量。用函数解决就行了,或者,如果真的有必要,使用atoms
或ref
s,这取决于你需要什么。
可以在函数中修改 atom
或 ref
以存储旧结果 - 这可能是您正在寻找的解决方案。
但是对于大多数情况,存在一个更简单的解决方案,不需要像 oldX
这样的变量——这就是函数式语言的好处。
您的代码
(defn rec [x y]
(if (not= x oldX)
(println "y"))
(def oldX x))
正如@cgrand 所说,def
只应在第一层使用。
您使用 if
,但您只定义了 true
情况。如果你只检查,如果某个陈述为真,那么你可以使用 when
.
最后一行在函数rec
的范围内定义了一个新的oldX
。这是活动命名空间中的 new 变量,而不是具有新值的旧变量(感谢 @user1571406)。
我认为您正在寻找的是这样的东西。我已尝试将您的 var 名称保留为原始名称,因此更容易看出差异。
- 使用
atom
存储oldX
- 使用
compare-and-set!
来确定你是否已经改变了原子 - 如果您更改了原子,请致电您的
(dosomething y)
注意: 这有点像 swap!
,除了 swap!
returns 换入的值,而不是你的调用 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!
,它会在失败时重现。