11

次の形式のマップがあるとします。

(def m {:a "A" :b "B"})

:a:bが両方とも nil でない場合、私は何かをしたい、私はすることができます:

(if-let [a (:a m)]
  (if-let [b (:b m)]
      ... etc ))

また

(if (and (:a m) (:b m))
  (let [{a :a b :b} m]
      ... etc ))

あるいは

(if (every? m [:a :b])
  (let [{a :a b :b} m]
      ... etc ))

これを達成するためのよりきちんとした(つまり、1行の)方法はありますか?

4

5 に答える 5

7

必要な動作を作成するには、ここでマクロが必要になる場合があると思います。私は(まだ)書いたことはありませんが、次の表現は、これがかなり簡単であることを示唆しています。

(let [{:keys [a b]} m]
   (when (every? identity [a b])
      (println (str "Processing " a " and " b))))

:keysバインドを破壊する形式を使用するevery?と、キーのベクトルの 1 つの指定でデストラクチャリングとチェックが可能になり、バインドされたローカルは次のコード ブロックで使用できます。

これは、次のようなマクロを作成するために使用できます。(when-every? [keys coll] code-with-bindings)

時間をかけてその方法を理解できる場合は、この回答をマクロコードで更新することがあります。

于 2012-07-26T18:07:03.100 に答える
6

Clojure の便利な機能であるmap destructuringを使用できます。andこれはまた、短絡している事実を悪用し、2 番目のマップで見つからない最初のマップのキーはnil、偽の値を取得します。

(let [{a :a b :b} {:a 1 :b "blah"}] 
  (and a b (op a b)))

さて、それは1行ではなく2nil行です....また、これはと他の偽の値を区別しません。

于 2012-07-26T17:46:43.153 に答える
1

not-any?これの良いショートカットです:

user> (not-any? nil? [(m :a) (m :b)])
true
user> (not-any? nil? [(m :a) (m :b) (m :d)])
false
user> 
于 2012-07-26T17:37:48.320 に答える