2014-12-07 21 views
0

我今天開始學習Clojure,遇到了一個我不會用切肉刀Googeling解決的問題。Clojure,redeclear變量引起警告「已經引用」

我有一個簡單的腳本,我想在條件滿足時增加計數器。我已經瞭解到變量在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

小問題與回答這個問題並無太大關係:''[......]無論你在'...'空間放置什麼,''總是'真實的' (如果[]:yes:no] =>:yes''(if [false]:yes:no)=>:yes''(if [1 2 3]:yes:no) =>:是等等等等 – noisesmith 2014-12-07 20:43:14

回答

0

有兩個問題在這裏:

,您會被遮蔽在clojure.core的功能。這會得到警告,因爲它可能會導致意外的行爲。如果你知道你將不會被使用clojure.core/num,您可以在您的命名空間聲明如下:

(ns my.ns 
    (:refer-clojure :exclude [num]) 
    ....) 

下一個問題是:def不是創建本地值。將def用作除頂級表單之外的任何東西幾乎總是一個錯誤,任何例外都需要非常明確的理由。它只能創建全局可變的var s。使用let作爲特定於一個作用域的綁定,就像在一個函數內部一樣。

(defn -main 
    [& args] 
    (let [num 0 
     num (if ... num (inc num))] 
    ...)) 

這裏,NUM不被突變,而不是作爲一個全球性的var創建的,但它是一個局部的結合由第二裝訂陰影。

0

短版本:

在Clojure中有特殊的抽象代表的東西,隨時間變化。最簡單的稱爲​​。您使用值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