2016-05-19 11 views
1

Ich weiß, wenn ich eine einfache find() Funktion wie (1 to 5).find(_ < 6) ausführen, werde ich immer wieder Some(1).Wird find() jemals nichtdeterministisch wirken?

Hier find() ist deterministisch und das gleiche Ergebnis immer wieder zurückkehren, obwohl die Sammlung (1 to 5) vier weitere Elemente enthält, die das Prädikat _ < 6 wahr machen.

Meine Frage ist - kann find() jemals nichtdeterministisch handeln?

Gibt es eine Sammlung und/oder ein Prädikat, das bei verschiedenen Ausführungen zu unterschiedlichen Ergebnissen führt (collection.find(predicate))?

+0

könnten Sie nur ein Prädikat verwenden, die zufällige Werte zurückgibt? Oder wollen Sie sich auf reine Prädikatfunktionen beschränken? – Bergi

+1

Verwenden Sie eine veränderbare Sammlung und ändern Sie sie zwischen den 'find' Ausführungen? Für Bonuspunkte, tun Sie es aus verschiedenen Threads. – Bergi

+0

Obwohl diese Vorschläge die Ergebnisse von 'find' definitiv ändern werden, war das nicht genau das, wonach ich suchte. Ich frage mich, ob 'collection.find (Prädikat)' jemals ein anderes Ergebnis für eine unveränderliche Sammlung und ein Prädikat zurückgeben würde. Zum Beispiel, wenn es eine Art von Sammlungsobjekt gäbe, würde das Finden nichtdeterministisch verlaufen? – Shuklaswag

Antwort

3

Bei einer linearen Sequenz wird find immer linear ablaufen und daher wird immer das gleiche Element zurückgegeben.

Dies gilt nicht unbedingt für eine nichtlineare Sammlung wie Set.

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

Hier erhalten Sie ein anderes Element, obwohl die Implementierung aufgrund der Gleichheit der Werte deterministisch zu sein scheint.

kann diese Gleichheit leicht gebrochen werden:

// 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" 

Ein anderer Fall ist parallel Sammlungen:

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

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

Ich versuche Ihren Code zu verstehen. Ich verstehe, dass '(1 bis 5) .map (neue Box (_))' den Bereich in einen Vektor von Boxen umwandelt.Aber warum konvertiert das Konvertieren des Vector of Boxes in ein Set die Reihenfolge, aber das Konvertieren des Range in ein Set funktioniert nicht? – Shuklaswag

+0

Vielleicht sollte es geschrieben werden als '(1 bis 5) .map (neue Box (_)). AsSet' – EECOLOR

+1

@Shuklaswag, weil das Set seine Backing-Array auf Hash-Codes organisiert. Bei Verweistypen, es sei denn, Sie implementieren spezifisch 'hashCode', das ist der Speicherort des Objekts, so dass Sie in jedem Lauf zufällige Hash-Codes und somit zufällige Sortierreihenfolge haben. –

Verwandte Themen