Clojure:关于when-let和if-let的文档语法

时间:2012-04-06 02:40:37

标签: syntax clojure

我一直在关注if-let和when-let宏,我无法确定它们“做”到底是什么。特别是文档sais:

clojure.core/when-let
([bindings & body])
Macro
  bindings => binding-form test

  When test is true, evaluates body with binding-form bound to the value of test

因此我对宏的记录方式感到有些困惑。

1)“=>”是什么象征意味着?

2)“测试”指的是什么?

3 个答案:

答案 0 :(得分:4)

直接回答您的问题:

  1. =>表示“扩展为”,如BNF表示法。在这种情况下,它意味着您需要两种形式:绑定表单和测试。
  2. “test”表示可以评估为bool的任何内容。
  3. 顺便说一下,我认为这里的文档不清楚甚至可能是错误的。很难(或不可能)推断构成绑定的两种形式需要被包含在向量中。恕我直言,它应该是when-let ([[bindings] & body])(args中显示的向量)或bindings => [binding-form test](BNF类扩展中显示的向量)。

答案 1 :(得分:4)

在处理宏来调用macroexpand并查看生成的代码是什么时,这通常很有用。

(macroexpand
    '(if-let [x (myfunc)]
       (foo x)
       (bar))

; expands to

(let* [temp__3695__auto__ (myfunc)] 
   (if temp__3695__auto__ (clojure.core/let [x temp__3695__auto__] 
     (foo x)) 
     (bar)))

; the generated symbols are necessary to avoid symbol 
; capture but can confuse. The above is equivalent to:

(let* [ t (myfunc)]
    (if t
       (let [x t]
           (foo x))
       (bar))

因此,您可以看到if-let是“将局部变量绑定到函数调用结果的简写,如果该变量是真实的,则调用第一个表单,否则调用另一个表单。您返回的值功能仅适用于'truthy'分支。“

文件惯例

bindings => binding-form test
  1. =>读取的内容类似于'等同于'
  2. test是一种返回值的表单
  3. 对于大多数这些功能,clojuredocs是您的朋友,示例用法通常会澄清事情。如果clojuredocs示例没有为您剪切,您可以添加自己的

答案 2 :(得分:2)

请考虑以下代码:

(if-let [x (a-function)]
  (do-something-with x) ;; (a-function) returned a truthy result
  (do-something-else)   ;; (a-function) returned nil or false

这与let类似,因为x将绑定到(a-function)的返回值。此函数可以返回nilfalse。在这种情况下,隐式测试失败,将评估(do-something-else)。如果x不是nil而不是false,则会评估(do-something-with x)

这可能有用的场景:

(if-let [user (find-logged-in-user)]
  (do something with logged in user) ;; a user was found
  (redirect to login page)           ;; no user was found

我有时使用类似下面的内容,有条件地将键添加到选项地图中:

(apply merge {:username "joe"
              :email "joe@example.com"}
             (when-let [name (find-full-name)] {:name name})
             (when-let [dob (find-date-of-birth)] {:dob dob}))

这会生成包含:username:email键的地图,如果找到用户的全名则会生成:name键,如果是日期则会生成:dob键出生了。

我希望这会使if-letwhen-let的使用更加清晰。