上一个函数输入参数正确存储

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 的方式是不使用变量。用函数解决就行了,或者,如果真的有必要,使用atomsrefs,这取决于你需要什么。

可以在函数中修改 atomref 以存储旧结果 - 这可能是您正在寻找的解决方案。

但是对于大多数情况,存在一个更简单的解决方案,不需要像 oldX 这样的变量——这就是函数式语言的好处。

您的代码

(defn rec [x y]  
  (if (not= x oldX)
    (println "y"))
  (def oldX x))

正如@cgrand 所说,def 只应在第一层使用。

您使用 if,但您只定义了 true 情况。如果你只检查,如果某个陈述为真,那么你可以使用 when.

最后一行在函数rec的范围内定义了一个新的oldX。这是活动命名空间中的 new 变量,而不是具有新值的旧变量(感谢 @user1571406)。

我认为您正在寻找的是这样的东西。我已尝试将您的 var 名称保留为原始名称,因此更容易看出差异。

  1. 使用atom存储oldX
  2. 使用compare-and-set!来确定你是否已经改变了原子
  3. 如果您更改了原子,请致电您的 (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!,它会在失败时重现。