我不明白在使用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