2015-05-09 68 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 
相关问题