Sometimes when you use underscores as placeholders
for parameters,
the compiler might not have enough information to infer missing parameter
types. Therefore, you need to explicitly provide type information. Placeholder syntax act as a “blank” in the expression that needs to be “filled in" and you can fill any value to it. Therefore, compiler will have no information about the type of this placeholder.
val foo = _ + _
//will fail - error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
The above expression will fail, because compiler will unable to find type of value that fill the placeholder. Therefore, there need to be some way for compiler to know the type. The one way is to provide type information of variable/method explicitly.
val foo: (String, String) => String = _ + _
The above expression will successfully compiled. Because, compiler resolve type of the parameter from type of variable foo
(1st and 2nd placeholder are both as String
).
In certain case, compiler can resolve the type from value:
List(1,2,3).foreach(println(_))
In above case, List(1,2,3)
is a List of type Int
, hence compiler will know type information of placeholder in println(_)
as Int
which is resolved from value of List
.
In addition, you can also provide type of value explicitly in order to let compiler know about type.
val foo = (_:String) + (_:String) //will return function (String, String) => String
In certain case, if your method have only one parameter, then you don't need to provide explicit type parameter otherwise you need to provide type for placeholder syntax as below:
scala> def firstResponse(r: Array[String]): String = r(0)
firstResponse: (r: Array[String])String
scala> val foo = firstResponse(_) //no need to provide type information
foo: Array[String] => String = <function1>
scala> def firstResponse2(r: Array[String], index:Int): String = r(index)
firstResponse2: (r: Array[String], index: Int)String
scala> val foo = firstResponse2(_, 3) //will fail, need to provide type information.
<console>:12: error: missing parameter type for expanded function ((x$1) => firstResponse2(x$1, 3))
val foo = firstResponse2(_, 3)
^
scala> val foo = firstResponse2((_:Array[String]), 3)
foo: Array[String] => String = <function1>
Now coming to your case:
val heuristics = Array(
firstResponse(_), mostFrequent(_, 3), mostFrequent(_, 4), mostFrequent(_, 5)
)
Here, compiler will have no idea of what is the type because:
- val heuristics have no type
- Type for placeholder syntax is not explicitly provided.
You have solve the issue by providing type Array[Array[String] => String]
to heuristics val
as in case 1, and hence compiler compiles it fine.
For case 2, you can modify your code as below:
val heuristics = Array(
firstResponse(_), mostFrequent(_:Array[String], 3), mostFrequent(_:Array[String], 4), mostFrequent(_:Array[String], 5)
)