2016-02-11 10 views
10

なぜキーと値がベクトルに作用しないのですか?私は、多くの場合、私は本当に私はベクトルやマップを持っているかどうか気にしないような状況で自分自身を見つける

[:foo :bar :baz :qux] 
{0 :foo, 1 :bar, 2 :baz, 3 :qux} 

重要な機能(getassocなど)の両方で動作します。 dissocのようなものはベクトルには作用しませんが、そうしないとよい理由があります。

しかし、keysvalsがマップ上で動作し、がベクターではなくではないことはわかりません。このようなものが実装されていない(またはより洗練された多態性の解決策がある)理由がありますか?何の正当な理由がない場合

(defn keys [m] 
    (if (vector? m) 
    (seq (range (count m))) 
    (clojure.lang.RT/keys m))) 

(defn vals [m] 
    (if (vector? m) 
    (seq m) 
    (clojure.lang.RT/vals m))) 

は、どのように私はこれが標準のClojureで実装を取得しようとして行くことができますか?

答えて

5

私はそれがメリットがある有効な考えだと思います。

どの機能を使用するべきか、何をエラーにするべきかの問題は、線を引くのが難しいです。一方の言語では、あなた自身を傷つけることができるように、過度に許容することができます(JavaScript?)。もう一方の端では、(C?)を構成する強力な抽象化がなくても、あなたは残されているように処方箋を書くことができます。

この特定のケースでは、マップを必要とするがベクトルに渡されるコードを記述しているときにエラーを検出する機能を提供しています。より汎用的なコードを書くことができるという利点があります。個人的には、誤った型のコレクションを関数に渡し、何かをするよりも爆発する方が好きなので、エラーとして扱われるのが好きです。

keysをベクトルに呼び出すのは混乱しますが、ベクトルにはキーがないためインデックスが付けられます。私にとっては、彼らは違うものです。したがって、ベクトルにkeysを呼び出すコードを記述すると、おそらくエラーになります。ベクトルのカウントと同じサイズの範囲が本当に必要な場合は、明示的に書きます。マップとベクトルの両方を扱える関数を用意したい場合は、キーまたは範囲の数を選択するために条件付きの型を使用します。明らかにこれらは私の好みに過ぎませんが、私にとってはkeysがベクター上で動作することを望まない重要な理由です。具体的な理由は、間違いを検出したいからです。

ただし、ベクトルで作業することをお勧めします。それらがインデックスで関連付けられていることがわかります。

dissocも同様に動作する必要がありますが、他の人がなぜそうではないと主張するのでしょうか? (dissoc [1 2 3] 0) -> [2 3]) Clojureがrbb-vectorを採用した場合、O(1)の要素を削除できないため、パフォーマンス上の問題があります。あなたがその操作をしなければならないときに非常に便利なことがあります。それはsomething people need to doであり、Clojureではかなり醜い不透明です!私たちのどちらもこれを機能にしたいとは思っていませんが、状況によっては本当にエレガントになると思います。しかし、実際には技術的な制限の事例ではなく、私たちはそのように好むだけです。

Clojureには開かれているcontributionプロセスがあります。 Clojure Dev Googleグループで他人と何をしようとしているのかを話し合ってください。彼らは、より質の高い変更とよりスムーズな提出プロセスをもたらすコメントや提案を提供することができるでしょう。 CAを提出したら、JIRA経由でパッチを提出できます。

誰でもバグや拡張リクエストをClojureに提出できます。 寄稿者同意書に署名した人は、パッチを提供したりチケットを改善することができます。 審査員には、プロセスのステージの一部を介してチケットを移動する機能が付与されています。 BDFL - Rich HickeyはClojureに入るものの創造者であり、生きがいのある独裁者です。 Stuart Hallowayには特別なレベルのアクセス権があり、通常はClojureにパッチを適用します。

もしこれがClojureにとって良い変更だと思えたら、まずClojure Groupでそれについて話し合って、そのアイディアのサポートを得てからClojure Dev Groupにそれを持って来ることをお勧めします。一般的に、あなたのアイデアは、「ここで価値を示す大きなユースケース」や「他の人が同じ価値観を望むいくつかの議論」などのサポートアーティファクトがあるときに最も効果的です。コレクションモデル再背景として

+3

私は感想に同意しますが、これがもたらす最大の問題はマップのベクトル表現が問題になることです。つまり、 '(seq {:foo:bar、1 2})=> [[: foo:bar] [1 2] ' この変更が与えられたら、 '(into {} [:foo:bar 1 2])=> {0:foo、1:bar、2 1、3 2 } ' 実際にはかなり混乱しているIMO –

+1

' dissoc [1 2 3] 0) 'が' [2 3] 'を返すということを明確にするために、 '{0 2、1 3}'マップと等価になります。一方、 '(dissoc {0 1、1 2、2 3} 0)'は '{1 2、2 3}'を返します。これは完全に別のマップです。 –

+1

確かに違いはありますが、それはなぜ問題なのですか? –

1

http://insideclojure.org/2016/03/16/collections/

キーとヴァルスは、両方のマップエントリのseqableを取る関数として定義されています。そのような定義を与えても、ベクトルのようなコレクションは一連のエントリではなく、むしろベクトル値のseqを生成するため、連想特性を持つコレクションを取るためにそれを広げることは容易ではありません。エントリをマップするためのseqの機能は、マップによってのみ提供されるものです。

はい、いずれにも作用する関数を作成することは可能ですが、そうすることで、これらの関数の既存の規約が破られて拡張されることはないと思います。

最初にこのようにしておくべきかどうかという設計上の問題に、それは私が言うのが難しいことです。

関連する問題