I have the following Scala code.
import scala.actors.Actor
object Alice extends Actor {
this.start
def act{
loop{
react {
case "Hello" => sender ! "Hi"
case i:Int => sender ! 0
}
}
}
}
object Test {
def test = {
(Alice !? (100, "Hello")) match {
case i:Some[Int] => println ("Int received "+i)
case s:Some[String] => println ("String received "+s)
case _ =>
}
(Alice !? (100, 1)) match {
case i:Some[Int] => println ("Int received "+i)
case s:Some[String] => println ("String received "+s)
case _ =>
}
}
}
After doing Test.test
, I get the output:
scala> Test.test
Int received Some(Hi)
Int received Some(0)
I was expecting the output
String received Some(Hi)
Int received Some(0)
What is the explanation?
As a second question, I get unchecked
warnings with the above as follows:
C:\scalac -unchecked a.scala
a.scala:17: warning: non variable type-argument Int in type pattern Some[Int] is unchecked since it is eliminated by erasure
case i:Some[Int] => println ("Int received "+i)
^
a.scala:18: warning: non variable type-argument String in type pattern Some[String] is unchecked since it is eliminated by erasure
case s:Some[String] => println ("String received "+s)
^
a.scala:22: warning: non variable type-argument Int in type pattern Some[Int] is unchecked since it is eliminated by erasure
case i:Some[Int] => println ("Int received "+i)
^
a.scala:23: warning: non variable type-argument String in type pattern Some[String] is unchecked since it is eliminated by erasure
case s:Some[String] => println ("String received "+s)
^
four warnings found
How can I avoid the warnings?
EDIT: Thanks for the suggestions. Daniel's idea is nice but does not seem to work with generic types, as in the example below
def test[T] = (Alice !? (100, "Hello")) match {
case Some(i: Int) => println ("Int received "+i)
case Some(t: T) => println ("T received ")
case _ =>
}
The following error warning is encountered: warning: abstract type T in type pattern T is unchecked since it is eliminated by erasure
This is due to type-erasure. The JVM does not know of any type parameter, except on arrays. Because of that, Scala code can't check whether an Option
is an Option[Int]
or an Option[String]
-- that information has been erased.
You could fix your code this way, though:
object Test {
def test = {
(Alice !? (100, "Hello")) match {
case Some(i: Int) => println ("Int received "+i)
case Some(s: String) => println ("String received "+s)
case _ =>
}
(Alice !? (100, 1)) match {
case Some(i: Int) => println ("Int received "+i)
case Some(s: String) => println ("String received "+s)
case _ =>
}
}
}
This way you are not testing what the type of Option
is, but what the type of its contents are -- assuming there is any content. A None
will fall through to the default case.