2015-05-09 40 views
1

我不明白在使用let時有什麼樣的優點或缺點,因爲在下面的代碼中可以避免使用let?爲什麼在函數中使用* let *?

(defn make-adder [x] 
    (let [y x] 
    (fn [z] (+ y z)))) 
(def add2 (make-adder 2)) 

;; or without let 
(defn add2 [z] (+ 2 z)) 

(add2 4) 
+0

這裏有兩件事情 - 一個函數可以生成函數,也可以使用let。你的最後一個例子是去掉兩個。 – pete23

回答

7

在大多數編程語言中,你可以聲明和使用局部變量幫助你在設計函數(或方法)體。在Clojure中,let讓你局部符號綁定到可以導致值,數據結構或其他本地函數定義的任何表達式。

您的示例非常簡單,不需要let構造,但您很快就會遇到對功能邏輯可讀性有很大幫助的情況。

let也是一種分解代碼的方法,它通過計算一次表達式並在幾個地方使用結果來提高可讀性和性能。

而且,最後但並非最不重要的是,letdestructuring在表達式返回複合結構(如集合)時可以非常方便地生成簡潔的代碼。

7

有三個主要原因命名中間結果:

  1. 你想幫助程序員(包括你自己),瞭解它們是什麼,下了線。
  2. 您想緩存它們,以便可以在多個位置使用它們,而無需再次評估表達式。如果評估你的表情有副作用,並且你只希望他們發生一次,這一點尤其重要。
  3. 您正在創建一個closure,它將使用let作爲名稱,但不會將它發佈給外部世界。

在你的make-adder例子中,let沒有真正需要,因爲它只是爲傳入參數建立一個別名。但是如果你有更多的參與,那麼這些優勢開始變得相關。

只是因爲我有手,這裏是從another recent answer of mine一些代碼:

(defn trades-chan 
    "Open the URL as a tab-separated values stream of trades. 
    Returns a core.async channel of the trades, represented as maps. 
    Closes the HTTP stream on channel close!" 
    [dump-url] 
    (let[stream (-> dump-url 
       (client/get {:as :stream}) 
       :body) ;;This is an example of 3. 
     lines (-> stream 
       io/reader 
       line-seq) 
     ;; This is an example of 2. I don't want to make multiple readers just because I use them in multiple expressions. 

     ;;fields and transducer are examples of 1. 
     fields (map keyword (str/split (first lines) #"\t")) 
     transducer (map (comp #(zipmap fields %) #(str/split % #"\t"))) 

     ;;output-chan is another example of 2 
     output-chan (async/chan 50 transducer)] 
    (async/go-loop [my-lines (drop 1 lines)] 
        (if (async/>! output-chan (first my-lines)) 
        (recur (rest my-lines))   
        (.close stream))) ;;Here, the closure closes the HTTP stream, so it needs a name to refer to it by.    
    output-chan)) 
2

的問題不在於是否使用let,但是否直接定義add2功能或使用功能,使功能,make-adder,做到這一點。

你的函數的決策功能是

(defn make-adder [x] 
    (let [y x] 
    (fn [z] (+ y z)))) 

由於@user1571406說,該let什麼都不做這裏有用,並更好地省略,給

(defn make-adder [x] 
    (fn [z] (+ x z))) 

...這是很容易讀。我們可以看到,給定一個數字,它返回一個函數,增加了不管它呈現的是數量:

((make-adder 2) 4) 
;6 

給予(make-adder 2)一個名字只是混亂。

定義它明確,即增加了2一個匿名函數是

(fn [z] (+ 2 z)) 

將其應用於4

((fn [z] (+ 2 z)) 4) 
;6 
相關問題