2012-09-26 19 views
4

我正在閱讀Programming Clojure第2版,並在第49頁上介紹了Clojure的for循環結構,它實際上是一個序列理解。Clojure序列解析中是否存在變量?

作者建議如下代碼:

(defn indexed [coll] (map-indexed vector coll)) 

(defn index-filter [pred col] 
    (when pred 
    (for [[idx elt] (indexed col) :when (pred elt)] idx))) 

(index-filter #{\a} "aba") 
(0 2) 

...最好一個基於Java的當務之急例子,給出的證據是,它的「使用高階函數...功能任何索引都可以避免變量的所有需求。「

什麼是「idx」,「elt」如果它們不是變量?除了累加器之外,它們是否意味着變量?

另外,爲什麼#{\ a}而不是「a」?

回答

4
  1. 在功能語言中沒有變量。實際上,您需要區分變量idx它只是一個綁定到具體值的名稱,並且您不能重新分配它(,但您可以將其重新設置爲另一個值)。

  2. 函數index-filter的第一個參數是謂詞,表示函數返回truefalse。這是一個數據結構set,但它也可以像一個函數一樣對待。如果將元素作爲參數傳遞給set函數,則返回此參數(如true),如果元素存在,並且爲零(否則爲false)。所以,你可以考慮一下這款集謂語匿名函數寫得比較容易理解的方式#(contains? #{\a} %)

+0

本章前面他們討論了「變量」,即(def a 1)。我想我困惑的地方是一個變量和一個不斷變化的值之間的差異。這是否實際上爲每次迭代在內存中創建idx1,idx2,idx3等,並且當idx被取消引用時,它會返回保存的最後一個值idx? –

+1

你只是不能改變其定義範圍內的界限值。所以舉例來說,每個迭代都具有'idx'的確切值,並且不能像命令式語言那樣簡單地重新分配它 – mishadoff

+0

變量是實際的內存位置,其內容可以被讀取和寫入。列表理解中的綁定,如(let [] ...)表達式,在本質上更具有詞法性 - 您可以將這裏的符號想象爲在評估表達式時被替換爲實際值的佔位符。 – Alex

5

pred功能 - #{\a}是包含字符集。在Clojure中,set是一個函數,如果它包含它的參數\a,則返回true。您也可以使用#(= % \a)(fn [x] (= \a x))

正如其他答案所暗示的,「在創造這個例子時沒有創造任何狀態。」 idxelt功能類似於變量,但僅侷限於for序列理解,所以代碼更緊湊,不是有狀態的,並且可以更清楚地說明(一旦您習慣了序列理解,至少:-)) - 也許是文字在這一點上並沒有達到最佳清晰度。

+0

pred的有用說明,謝謝 –