Reputation: 13136
I am trying to create a map of lambda functions in Scala
val identity = ((x:Any) => x)
val propmap = Map("references-count" -> identity,
"title" -> ((x:List[String]) => x(0)),
"score" -> identity,
"issued" -> ((x:List[Any]) => x(0)))
when I type propmap("score")
or propmap("title")
the output I get is the same: <function1>
.
Running identity(10.1)
returns the expected result. However
val f1 = propmap("score")
f1(10.9)
results in:
Name: Unknown Error
Message: <console>:29: error: type mismatch;
found : Double(10.9)
required: List[String]
f1(10.9)
^
StackTrace:
Seemingly the function is overwritten. Where to go for the besung immutabilty?
Upvotes: 0
Views: 308
Reputation: 13001
The problem is the type of propmap.
Scala infers the type as String, (List[String] => Any)
The reason for that is that scala needs to infer a type which matches ALL values. The String as key is obvious but for the function, it needs to find a function type which matches all functions. Since all functions have 1 parameter this would be function1.
If you look at the definition of function1 you would see it is:
trait Function1[-T1, +R] extends AnyRef
This means that it needs to find the first type to be the most constrictive. In this case this is List[String] and therefore it expects a function List[String]=>Any (this actually makes sense because you want a type you can use on ALL functions).
So scala automatically converts your identity function to be (x: List[String] => x) in practice and therefore when you try to pass it a number it fails.
Possible solutions:
The first solution as mentioned by @KotWarm would be to use asInstanceOf:
val f1 = propmap("score").asInstanceOf[Any ⇒ Any]
println(f1(10.9))
The second solution would be to rewrite the functions to use Any, for example:
val propmap = Map("references-count" -> identity,
"title" -> ((x: Any) => x.asInstanceOf[List[String]](0)),
"score" -> identity,
"issued" -> ((x: Any) => x.asInstanceOf[List[Any]](0)))
Upvotes: 2
Reputation: 626
Because scalac determined the type of collection as
propmap: scala.collection.immutable.Map [String, List [String] => Any]
Determine the type of your collection explicitly so that the compiler knows what you want to get
Here is an example code
val identity = ((x:Any) => x)
val propmap = Map[String,_ => _]("references-count" -> identity,
"title" -> ((x:List[String]) => x(0)),
"score" -> identity,
"issued" -> ((x:List[Any]) => x(0)))
But to execute the methods you must cast the type
val f1 = propmap("score").asInstanceOf[Any ⇒ Any]
println(f1(10.9))
Upvotes: 1