2016-05-19 1 views
1

(1 to 5).find(_ < 6)のような単純なfind()関数を実行すると、私はいつもSome(1)に戻ります。()が非決定的に作用することはありますか?

ここで、(1 to 5)には述語を真にする4つの他の要素が含まれていますが、find()は確定的で、常に同じ結果を返します。_ < 6

私の質問は - find()は決して非決定的に行動できないのですか?

collection.find(predicate)に連続して実行される結果が異なるようにするコレクションおよび/または述語が存在しますか?

+0

あなただけのランダムな値を返す述語を使用することができますか?または、あなた自身を純粋な述語関数に限定したいですか? – Bergi

+1

変更可能なコレクションを使用し、 'find'実行間で変更しますか?ボーナスポイントは、別のスレッドから行います。 – Bergi

+0

これらの提案は間違いなく 'find'の結果を変更しますが、それは私が探していたものとはまったく異なります。私は 'collection.find(predicate)'が変わらないコレクションと述語で異なる結果を返すかどうか疑問に思っていました。例えば、findが非決定的にトラバースするコレクションオブジェクトがあれば? – Shuklaswag

答えて

3

線形シーケンスの場合、findは常に線形に進むため、常に同じ要素が返されます。

これは、Setのような非線形コレクションでは必ずしも真ではありません。

Set(1 to 5: _*).find(_ < 6) // Some(5) 
Set(1 to 5: _*).find(_ < 6) // Some(5) 

ここでは、値の平等のために実装が決定的であるように見えますが、ここでは別の要素があります。この等式は簡単に分けることができます

// reference equality 
class Box(val peer: Int) { override def toString = peer.toString } 

def mkIndet() = Set((1 to 5).map(new Box(_)): _*) 

mkIndet.find(_.peer < 6) // "random" 
mkIndet.find(_.peer < 6) // "random" 
mkIndet.find(_.peer < 6) // "random" 

別のケースでは、並列コレクションです:

def par() = (1 to 10000).par.find(i => i % 1000 == 0) 

par() // "random" 
par() // "random" 
par() // "random" 
+0

私はあなたのコードを理解しようとしています。私は '(1〜5).map(new Box(_))'がRangeをBox of Vectorに変換することを理解しています。しかし、BoxのVectorをSetに変換すると、順序がランダム化されますが、RangeをSetに変換するのはなぜですか? – Shuklaswag

+0

セットはハッシュコードに基づいてバッキング配列を編成するため、@ Shuklaswagという名前の '.map(new Box(_))。asSet' – EECOLOR

+1

と書くべきでしょう。参照型については、オブジェクトのメモリ位置である 'hashCode'を具体的に実装しない限り、それぞれの実行でランダムなハッシュコードとランダムなソート順があります。 –

関連する問題