我不明白在使用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)
我不明白在使用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)
在大多數編程語言中,你可以聲明和使用局部變量幫助你在設計函數(或方法)體。在Clojure中,let
讓你將局部符號綁定到可以導致值,數據結構或其他本地函數定義的任何表達式。
您的示例非常簡單,不需要let
構造,但您很快就會遇到對功能邏輯可讀性有很大幫助的情況。
let
也是一種分解代碼的方法,它通過計算一次表達式並在幾個地方使用結果來提高可讀性和性能。
而且,最後但並非最不重要的是,let
destructuring在表達式返回複合結構(如集合)時可以非常方便地生成簡潔的代碼。
有三個主要原因命名中間結果:
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))
的問題不在於是否使用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
這裏有兩件事情 - 一個函數可以生成函數,也可以使用let。你的最後一個例子是去掉兩個。 – pete23