我是Clojure的新手,我很难理解一些概念,特别是纯函数和不变性。
我仍然无法理解的一件事是如何在clojure中解决这样的问题:
具有登录方法的简单控制台应用程序,在该应用程序中,用户在1分钟的间隔内不能尝试登录3次以上。
例如,在C#中,我可以在用户每次尝试登录时将UserId和时间戳添加到集合中,然后检查最后一分钟是否有3个以上的尝试。
考虑到我无法更改收藏夹,我该如何在Clojure中做到这一点?
这不是一个务实的问题(尽管会欢迎一些代码示例),我想了解您如何解决这样的问题。
答案 0 :(得分:5)
在大多数情况下,您不会更改对象,而是创建旧对象的新版本:
(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
。