6

この質問のフォローアップ: Idiomatic clojure map lookup by keyword

clojure を使用したマップへのアクセスは、さまざまな方法で行うことができます。

(def m {:a 1}

(get m :a) ;; => 1
(:a m) ;; => 1
(m :a) ;; => 1

私は主に 2 番目の形式を使用し、時には 3 番目の形式を使用し、最初の形式を使用することはほとんどありません。それぞれを使用する利点 (速度/構成可能性) は何ですか?

4

6 に答える 6

12

getマップが nil または not-a-map の可能性があり、キーが呼び出し不可能なもの (つまり、キーワードではない) の可能性がある場合に役立ちます。

(def m nil)
(def k "some-key")

(m k)  =>  NullPointerException
(k m)  =>  ClassCastException java.lang.String cannot be cast to clojure.lang.IFn

(get m k)  =>  nil
(get m :foo :default)  =>  :default
于 2013-01-23T23:02:05.423 に答える
3

clojureの Web ページを見ると、

マップは、オプションの 2 番目の引数 (デフォルト値) を持つ 1 つの引数 (キー) の invoke() に対して IFn を実装します。つまり、マップはそれらのキーの関数です。nil キーと値は問題ありません。

Clojure の内部を覗いてみると、やりがいを感じることがあります。invoke地図でどのように見えるかを調べると、次のように表示されます。

https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/APersistentMap.java#L196

valAtマップのメソッドを呼び出しているようです。

getマップで呼び出されたときに関数が何をするかを見ると、これは への呼び出しclojure.lang.RT.getであり、これは実際には への同じ呼び出しにvalAt要約されます (マップはAssociativesであるため ILookUp を実装します)。

https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L634 .

キーと not-found-value で呼び出されたマップについても同じことが言えます。それで、利点は何ですか?どちらの方法もほとんど同じに要約されるため、パフォーマンスに関しては何も言うことはありません。それは単なる構文上の利便性です。

于 2013-01-23T21:53:51.120 に答える
2

データをいじるために HOF を構築するためgetにetc に渡すことができますが、頻繁には発生しません。partial

user=> (def data {"a" 1 :b 2})
#'user/data
user=> (map (partial get data) (keys data))
(1 2)

データに文字列がキーとして含まれている場合、3 番目の形式をよく使用します

于 2013-01-23T21:45:23.653 に答える
1

速度の違いはないと思いますし、あったとしてもそれは実装の詳細になります。

個人的には、2 番目のオプション (:am) の方が好みです。コードが見やすくなる場合があるからです。たとえば、一連のマップを反復処理する必要があることがよくあります。

(def foo '({:a 1} {:a 2} {:a 3}))

:a のすべての値をフィルタリングしたい場合は、次を使用できます。

(map :a foo)

それ以外の

(map #(get % :a) foo)

また

(map #(% :a) foo)

もちろん、これは個人的な好みの問題です。

于 2013-01-23T20:58:50.940 に答える
0

キーワード ファースト アプローチを使用する利点の 1 つは、マップが nil の場合に寛容な動作で値にアクセスする最も簡潔な方法であることです。

于 2013-01-25T08:53:07.997 に答える