Scala Range contains(elem: Any) method
Apparently Range
has a method that checks if it contains a value of type Any. I understand that it is from SeqLike
, but causes some problems.
For instance, i was matchin开发者_Go百科g hours from joda.DateTime:
DateTime.now match {
case d if 0 to 12 contains d.hourOfDay() => ...
Here d.hourOfDay() returns DateTime.Property, not Int, but code still compiles, because of contains(elem: Any)
. Is there any way to check for such calls at compile time?
You can use Scalaz's typesafe equals (===
) in conjunction with exists
method on TraversableOnce
.
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> 1 to 5 exists { _ === 2 }
res1: Boolean = true
scala> 1 to 5 exists { _ === "Hullo" }
<console>:14: error: type mismatch;
found : java.lang.String("Hullo")
required: Int
1 to 5 exists { _ === "Hullo" }
^
You can pimp Range
to add a type-safer contains method:
class SafeRange( range: Range ) {
def safeContains( i: Int ) = range contains i
}
object SafeRange {
implicit def safer( range: Range ) = new SafeRange( range )
}
Import the implicit and call safeContains
on any range instance:
scala> import SafeRange._
import SafeRange._
scala> (0 until 10) safeContains 3
res2: Boolean = true
scala> (0 until 10) safeContains 100
res3: Boolean = false
scala> (0 until 10) safeContains "foo"
<console>:18: error: type mismatch;
found : java.lang.String("foo")
required: Int
(0 until 10) safeContains
Based on the scaladocs for Range it looks like there's not a better Range method you could use. Your options seem to be
Use an explicit type signature:
case d if 0 to 12 contains (d.hourOfDay(): Int) => ...
Make your own method:
def containsInt(r: Range, i: Int) = ...
This seems to be a holdover from Java equals
being pre-generics, and is only one of the inconveniences this fact causes for Scala.
精彩评论