2016-09-13 14 views
6

Kiedy zadzwonićCzy Scala mapWartość leniwy?

System.err.println("Before") 
System.err.flush() 
val foo: Map[Int, T] = t mapValues (fn(_)) 
System.err.println(foo.head) //prevent optimiser from delaying the construction of 'foo' 
System.err.println("After") 
System.err.flush() 

z fn o instrukcji print debugowania wewnątrz, otrzymuję ten wynik:

Before 
...head item... 
After 
...debug print statement from fn... 
...debug print statement from fn... 

ja nie rozumiem, dlaczego sprawozdanie wydruk debug są nazywane po „po” jest drukowany i nie rozumiem, dlaczego otrzymuję go dwukrotnie, chyba że mapValues tworzy leniwą mapę?

Odpowiedz

8

Yes it is. Mapuje się do klasy pośredniej, która posiada fn i nie ocenia aż do uzyskania dostępu (raz za razem).

def mapValues[W](f: V => W): Map[K, W] = new MappedValues(f) 

Użyj surowego map, jeśli nie chcesz leniwej oceny. Czyli:

collection map { case (k, v) => (k, fn(v)) } 
+1

Najważniejszą cechą jest to, że nie trzeba ponownie mapować mapy po 'mapValues', ponieważ klucze się nie zmieniły. W przypadku 'map' z przykładu, kompilator nie może dać gwarancji. – dveim

4

Należy pamiętać, że realizacja MappedValues ocenia funkcję na każdym dostępu - różne od Scala lazy val że ocenia się tylko raz. Po przejściu przez kod może być widoczne dwukrotne wyjście. Poszerzenie okna val foo w oknie debugera spowoduje powtórzenie wartości, wywołanie funkcji fn i wygenerowanie danych wyjściowych debugowania.

Jeśli podasz kod mapy t i funkcję fn, możemy Ci pomóc.

+0

W porządku - chodziło głównie o to, że (jak zawsze) nieoczekiwane zachowanie było niepokojące i wymagało raczej śledzenia, niż powodowania konkretnego problemu. Ale dziękuję za ofertę pomocy. – Mohan