Um die anderen Antworten zu ergänzen, hier einige Beispiele, die zeigen, warum Sie in einigen Fällen den "fehlenden Parametertyp" erhalten, wenn Sie '_' als Platzhalterparameter verwenden.
Scala-Typ-Inferenz berücksichtigt den 'erwarteten' Typ eines Ausdrucks basierend auf seinem Kontext. Wenn kein Kontext vorhanden ist, kann der Typ der Parameter nicht abgeleitet werden. Beachten Sie, dass in der Fehlermeldung die ersten und zweiten Instanzen von _
durch die vom Compiler generierten Kennungen x$1
und x$2
ersetzt werden.
scala> _ + _
<console>:5: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
_ + _
^
<console>:5: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
_ + _
^
einen Typ Zuschreibung auf den gesamten Ausdruck liefert die Rückschließer helfen genug Kontext hinzu:
scala> (_ + _) : ((Int, Int) => Int)
res3: (Int, Int) => Int = <function2>
Alternativ Sie einen Typ Zuschreibung auf jeden Parameter Platzhalter hinzufügen:
scala> (_: Int) + (_: Int)
res4: (Int, Int) => Int = <function2>
Im folgenden Funktionsaufruf mit den angegebenen Typargumenten ist der Kontext eindeutig und der Funktionstyp wird abgeleitet.
scala> def bar[A, R](a1: A, a2: A, f: (A, A) => R) = f(a1, a2)
bar: [A,R](a1: A,a2: A,f: (A, A) => R)R
scala> bar[Int, Int](1, 1, _ + _)
res5: Int = 2
Wenn wir jedoch bitten, den Compiler die Typparameter zu schließen, wenn nicht:
scala> bar(1, 1, _ + _)
<console>:7: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
bar(1, 1, _ + _)
^
<console>:7: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
bar(1, 1, _ + _)
^
Wir es helfen kann, aber durch die Parameterlisten currying. Hier sagen die Argumente für die erste Parameterliste (1, 1)
die Folgerung, dass der Typparameter A
Int
sein sollte. Er weiß dann, dass der Typ des Arguments f
(Int, Int) => ?)
sein muss, und der Rückgabetyp R
wird als Int
abgeleitet, das Ergebnis der Ganzzahladdition. Sie sehen den gleichen Ansatz, der in der Standardbibliothek in Traversable.flatMap
verwendet wird.
scala> def foo[A, R](a1: A, a2: A)(f: (A, A) => R) = f(a1, a2)
foo: [A,R](a1: A,a2: A)(f: (A, A) => R)R
scala> foo[Int, Int](1, 1) { _ + _ }
res1: Int = 2
scala> foo(1, 1) { _ + _ }
res0: Int = 2
@Scoobie Nur um dies zu verstärken, wird der Unterstrich für viele verschiedene Zwecke in Scala verwendet. Wie David erklärte, hat jede Verwendung in Ihrem Beispiel tatsächlich eine andere Bedeutung. Es gibt noch andere Bedeutungen - Unterstreichung, in Scala, ist ein ziemlich gutes Beispiel für Probleme, die sich aus der Überlastung von Operatoren ergeben. Während ich anfangs Probleme damit hatte, kann ich ehrlich sagen, dass ich noch nie darüber nachgedacht habe, wie ich es verbessern könnte. –