何时在Clojure中使用let vs. if-let

Art*_*ldt 36 clojure

何时使用if-let而不是let使代码看起来更好并且它是否会对性能产生影响?

har*_*rto 75

我想当你想在代码的" "部分引用一个条件值时,应该使用if-let:ifthen

即代替

(let [result :foo]
  (if result
    (do-something-with result)
    (do-something-else)))
Run Code Online (Sandbox Code Playgroud)

你写:

(if-let [result :foo]
  (do-something-with result)
  (do-something-else))
Run Code Online (Sandbox Code Playgroud)

这是一个小整洁,并为您节省更多水平.就效率而言,您可以看到宏扩展不会增加太多开销:

(clojure.core/let [temp__4804__auto__ :foo]
  (if temp__4804__auto__
    (clojure.core/let [result temp__4804__auto__]
      (do-something-with result))
    (do-something-else)))
Run Code Online (Sandbox Code Playgroud)

这也说明else了在代码的" "部分中不能引用绑定.

  • 此外,if-let的绑定向量中不可能有两个以上的表单.例如:( if-let [a 20 b nil](println a)) - 不起作用! (9认同)

fog*_*gus 34

一个很好的用例if-let是删除使用回指的必要性.例如,Arc编程语言提供了一个调用的宏aif,允许您在给定表达式求值为逻辑true时绑定itif表单主体内命名的特殊变量.我们可以在Clojure中创建相同的东西:

(defmacro aif [expr & body]
  `(let [~'it ~expr] (if ~'it (do ~@body))))

(aif 42 (println it))
; 42
Run Code Online (Sandbox Code Playgroud)

这是好的和好的,除了回指没有嵌套,但if-let确实:

(aif 42 (aif 38 [it it]))
;=> [38 38]

(aif 42 [it (aif 38 it)])
;=> [42 38]

(if-let [x 42] (if-let [y 38] [x y]))
;=> [42 38]
Run Code Online (Sandbox Code Playgroud)