2012-12-11 8 views
12

私はclojureマップを持っています。名前はoptsです。私は、キーを取得いくつかのデフォルト値が存在しない場合は、そのようなことを、このマップから値を取得するための2つの方法を知っている: clojureマップのデフォルト値

(let [opts {} 
     title-1 (or (:title opts) "Default title") 
     title-2 (:title opts "Default title")] 
    (println title-1 title-2)) 

は、私はいくつかのライブラリを見に(クイル、incanterは) orとの最初のアプローチを使用します。 2番目のアプローチはより簡潔できれいです。最初のアプローチには利点がありますか?
(or (:title opts) "Default value")を使用しないと、 falsenilを値として渡すことができなくなります。この場合、デフォルト値が常に使用されます。

+2

'(get opts:title"デフォルトのタイトル ")'を使用することもできます。 – ponzao

+0

@ponzao mapが 'nil'の場合、' get'は 'NullPointerException'を投げないので、さらに良いかもしれません。 'nil'または指定されていればデフォルト値を返します。 –

+0

@IvanKoblik '(:title nil" Default ")'もうまくいきます。 –

答えて

20

(or (:key hash) default)(:key hash default)の重要な違いは、前者が必要な場合にのみdefaultと評価するという事実です。後者の場合、常に評価されます。したがって、defaultの評価が高価な場合は、orを使用する必要があります。

ハッシュにブール値のコンテキストでfalseの値が含まれている場合、別の相違点が明らかになります。このような値の場合、(or (:key hash) default)は、falseまたはnilの代わりにdefaultと評価されます。 orの式とは対照的に、(:key hash default)は正しい結果をもたらします。補足として、nilを値としてハッシュに格納する前に、2度考えてください。

これは重要な違いです。さあ、マイナーなものに移動しましょう。

(or (:title opts) "Default title") 

;; Redacted for the sake of brevity. 
(let* [x (:title opts)] 
    (if x 
    x 
    "Default title")) 

を読者によって拡張された間違いなく、違いを推定することは困難である任意のベンチマークなしもちろん

(:title opts "Default title") 

を評価するだけよりも効率が低いですしかし、私はそれが限界的でなければならないと信じています。

一方、一見して(or (:key hash) :default)は、(:key hash :default)イディオムに慣れていない人にとっては理解しやすいようです。他の言語のプログラマーを考えてみましょう。 Rubyではインスタンスのハッシュの非existant要素を処理する典型的な方法は、最初の式が一定のClojureのイディオムに慣れていない人間が解析しやすいかもしれません、そのため

val = hash[:key] || :default 

です。

+2

私はあなたが一貫していなければならないということに全く反対しています。それぞれのスタイルが時折必要です。デフォルトの式の計算が非常に高価な場合は 'or'スタイルを、' nil'または 'false'が有効な値の場合はデフォルトでget-withを使い、" Nothing there "と" false or nil "を区別する必要がありますそこ"。 – amalloy

+0

@amalloy、コメントと重要な違いを指摘してくれてありがとう。私は答えを改訂しました。 – Jan

関連する問題