3

if-let マクロと when-let マクロを見てきましたが、それらが「行う」ことが正確に何であるかを判断するのに苦労しています。特に、ドキュメントには次のように記載されています。

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) 「テスト」とは何を指しますか?

4

3 に答える 3

4

あなたの質問への直接の答え:

  1. =>BNF表記のように、「に展開する」を意味します。この場合、バインディング フォームとテストの 2 つのフォームが必要であることを意味します。
  2. 「テスト」とは、bool として評価できるものすべてを意味します。

ところで、ここではドキュメントが不明確であるか、間違っている可能性さえあると思います。バインディングを構成する 2 つの形式をベクトルで囲む必要があると推測するのは困難 (または不可能) です。IMHOそれはwhen-let ([[bindings] & body])(引数に示されているベクトル)またはbindings => [binding-form test](BNFのような展開に示されているベクトル)のいずれかでなければなりません。

于 2012-04-06T07:00:06.940 に答える
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は「ローカル変数を関数呼び出しの結果にバインドし、その変数が真の場合は最初の形式を呼び出し、そうでない場合は他の形式を呼び出すことの省略形であることがわかります。関数によって返される値は、「真の」でのみ使用できます。 ' ブランチ。"

wrt ドキュメンテーション規約

bindings => binding-form test
  1. =>「と同等です」のようなものを読み取ります
  2. test値を返す何らかの形式です

これらの関数のほとんどについて、clojuredocsはあなたの友人です。使用例はしばしば物事を明確にします。clojuredocs の例ではうまくいかない場合は、独自の例を追加できます。

于 2012-04-06T07:19:38.703 に答える
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)。この関数はnil、 またはを返しfalseます。その場合、暗黙のテストは失敗し、(do-something-else)評価されます。xis notnilおよび notfalseの場合は(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-letそれが使いやすく、when-letより明確になることを願っています。

于 2012-04-06T03:04:04.357 に答える