我今天开始学习Clojure,遇到了一个我不会用切肉刀Googeling解决的问题。
我有一个简单的脚本,我希望在满足条件时增加一个计数器。我已经了解到Clojure中的变量是不可变的,而增加这种变量的方法是重新确定它,但这会引发警告。
(defn main[]
(def num 0)
(if [...]
(def num (+ num 1))
)
)
然而,这会引发以下警告:
WARNING: num already refers to: #'clojure.core/num in namespace: user, being replaced by: #'user/num
答案 0 :(得分:1)
这里有两个问题:
一,你正在影响clojure.core中的一个函数。这会收到警告,因为它可能导致意外行为。如果您知道自己不能使用clojure.core/num
,则可以在命名空间声明中包含以下内容:
(ns my.ns
(:refer-clojure :exclude [num])
....)
下一个问题:def
不适用于创建本地值。使用def作为顶级形式以外的任何东西几乎总是一个错误,任何例外都需要非常明确的理由。它只能创建全局可变var
。使用let
进行特定于一个范围的绑定,例如在函数内部。
(defn -main
[& args]
(let [num 0
num (if ... num (inc num))]
...))
这里,num没有变异,也没有创建为全局var
,但是它是一个被第二个绑定所遮蔽的本地绑定。
答案 1 :(得分:0)
简短版本:
在Clojure中,有一些特殊的抽象来表示随时间变化的东西。最简单的一个称为atom
。您使用值0
启动原子,然后通过将函数inc
应用于其值来更改原子。
(def n (atom 0))
(def -main
[& [args]]
(if condition
(swap! n inc))
...)
长版:
如果我理解正确,你就是在寻求一种绕不变性的方法。这意味着您要对一些概念(即网站访问者)进行建模,这些概念随着时间的推移会采用不同的值(即42)。 Clojure非常重视如何做到这一点,它提供的技术(STM)是语言的核心。 Clojure工作方式不同的原因是使并发更容易,但您不需要考虑并发以增加计数器。要理解Clojure背后的基本原理,我建议使用Rich Hickey的会谈,在这种情况下The Value of Values。