2011-12-22 24 views
44

podane:Scala Mapa foreach

val m = Map[String, Int]("a" -> 1, "b" -> 2, "c" -> 3) 
m.foreach((key: String, value: Int) => println(">>> key=" + key + ", value=" + value)) 

dlaczego kompilator skarżą

error: type mismatch 
found : (String, Int) => Unit 
required: (String, Int) => ? 

Odpowiedz

25

Ups, czytać DOCO źle, map.foreach spodziewa funkcją dosłowne z argumentem krotki!

tak

m.foreach((e: (String, Int)) => println(e._1 + "=" + e._2)) 

działa

+4

Biorąc pod uwagę, że typy są wnioskowane, można po prostu zrobić: m.foreach (e => println (e._1 + "=" + e._2) – virtualeyes

+0

Czy można wyświetlić cały typ? Istnieje wiele map , Obawiam się, który to jest. –

71

nie jestem pewien co do błędu, ale można osiągnąć to, co chcesz, co następuje:

m.foreach(p => println(">>> key=" + p._1 + ", value=" + p._2)) 

Oznacza to, że foreach przyjmuje funkcję, która pobiera parę i zwraca Unit, a nie funkcję t hat bierze dwa argumenty: tutaj, p ma typ (String, Int).

Innym sposobem jest napisać:

m.foreach { case (key, value) => println(">>> key=" + key + ", value=" + value) } 

W tym przypadku, blok { case ... } jest częściowym funkcja.

+0

to miłe, bardziej zgodne z dynamicznego języka obj.each podejścia {k, v => ...} i więcej czytelny niż krotki ._1, ._2 składnia – virtualeyes

+0

Co ciekawe, czy jest jakieś uwzględnienie wydajności dla drugiego użycia (przypadku)? Dla każdego elementu postaraj się o "case" przypisać je do zmiennej itp. Chcę, aby mój kod był czytelny, ale także aby był możliwie szybki. – endertunc

13

Musisz dopasować tupot na argumencie Tuple2, aby przypisać zmienne do podelementów key, value. Można zrobić z nielicznymi zmianami:

m.foreach{ case (key: String, value: Int) => println(">>> key=" + key + ", value=" + value)} 
+5

A przy okazji, możesz usunąć adnotacje typu z klucza i wartości. – Rogach

+0

@huitseeker Kocham cię bardzo serdecznie. –

5

Doskonałe pytanie! Nawet przy jawnym wpisywaniu metody foreach nadal pojawia się bardzo niejasny błąd kompilacji. Są na to sposoby, ale nie mogę zrozumieć, dlaczego ten przykład nie działa.

scala> m.foreach[Unit] {(key: String, value: Int) => println(">>> key=" + key + ", value=" + value)} 
<console>:16: error: type mismatch; 
found : (String, Int) => Unit 
required: (String, Int) => Unit 
       m.foreach[Unit] {(key: String, value: Int) => println(">>> key=" + key + ", value=" + value)} 
                 ^
14

Mylące komunikat o błędzie jest błąd kompilatora, który powinien być fixed in 2.9.2:

+0

Używanie skalac 2.9.2 i ten błąd pozostaje. – Renato

+0

Właśnie sprawdziłem (kompilując https://github.com/paulbutcher/baderrormessage przeciwko 2.9.1 i 2.9. 2). Widzę problem w 2.9.1, a nie w 2.9.2.Jeśli masz nadal przykład problemu, być może powinieneś ponownie otworzyć błąd? –

+0

Właśnie próbowałem kodu zamieszczonego w odpowiedzi przez @ (Eishay Smith) poniżej (uważam, że jest dokładnie taki sam problem, jak pokazano w pytaniu) z Scala 2.9.2 (Java HotSpot 1.7.0 VM dla Windows 64-bit) i może zobaczyć tę samą absurdalną wiadomość pokazaną w jego poście. – Renato

0

Jeszcze innym sposobem:

Map(1 -> 1, 2 -> 2).foreach(((x: Int, y: Int) => ???).tupled) 

Jednak to wymaga wyraźnej adnotacji typu, więc wolę funkcja częściowa.

1

Docs mówi argumentem jest krotka -> jednostka, więc możemy łatwo to zrobić

Map(1 -> 1, 2 -> 2).foreach(tuple => println(tuple._1 +" " + tuple._2)))