我是Clojure的新手,我很难理解一些概念,特别是纯函数和不变性。
我仍然无法理解的一件事是如何在clojure中解决这样的问题:
一个具有登录方法的简单控制台应用程序,用户无法在1分钟的间隔内尝试登录3次以上。
例如,在C#中,我可以在用户每次尝试登录时将UserId和时间戳添加到集合中,然后检查最后一分钟是否有3个以上的尝试。
考虑到我无法更改自己的收藏,我将如何在Clojure中做到这一点?
这不是一个务实的问题(尽管会欢迎一些代码示例),但我想了解您如何解决这样的问题。
在大多数情况下,您不更改对象,而是创建旧对象的新版本:
(loop [attempt-dates []] (if (login-is-correct) (login) (recur (conj attempt-dates (current-date-stamp)))))
在这种情况下,我使用loop
。无论我给什么,recur
都会传递给的下一个迭代loop
。我正在创建一个包含新标记的(conj attempt-dates (current-date-stamp))
新列表,然后将其传递到的下一个迭代loop
。
在大多数情况下,就是这样做的。与其考虑更改对象,不如考虑创建对象的转换后的副本并传递该副本。
如果您确实确实需要可变状态,则可以使用可变atom
状态来保存不可变状态:
(def mut-state (atom [])) (swap! mut-state conj 1) (println @mut-state) ; Prints [1]
[]
在这里仍然是不变的,新版本只是替换了可变atom
容器中的旧版本。
除非您需要与UI回调或类似功能进行通信,否则通常通常不需要可变性。练习使用loop
/ recur
和reduce
代替。