В дополнение к другим ответам, вот несколько примеров, показывающих, почему вы получаете «пропущенный тип параметра» в некоторых случаях при использовании «_» в качестве параметра-заполнителя.
Вывод типа Scala рассматривает «ожидаемый» тип выражения на основе его контекста. Если нет контекста, он не может определить тип параметров. Обратите внимание, что в сообщении об ошибке первый и второй экземпляры _
заменены на идентификаторы, сгенерированные компилятором x$1
и x$2
.
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))
_ + _
^
Добавление атрибута типа ко всему выражению обеспечивает достаточный контекст, чтобы помочь логическому выводу:
scala> (_ + _) : ((Int, Int) => Int)
res3: (Int, Int) => Int = <function2>
В качестве альтернативы, вы можете добавить атрибуцию типа для каждого заполнителя параметра:
scala> (_: Int) + (_: Int)
res4: (Int, Int) => Int = <function2>
В приведенном ниже вызове функции с предоставленными аргументами типа контекст однозначен, а тип функции выведен.
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
Однако, если мы попросим компилятор вывести параметры типа, в случае ошибки:
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, _ + _)
^
Мы можем помочь, хотя, путем каррирования списков параметров. Здесь аргументы первого списка параметров (1, 1)
говорят о том, что параметр типа A
должен быть Int
. Затем он знает, что тип аргумента f
должен быть (Int, Int) => ?)
, а тип возвращаемого значения R
выводится как Int
, результат сложения целых чисел. Вы увидите тот же подход, который использовался в Traversable.flatMap
в стандартной библиотеке.
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