题
显然 Range
有一个方法检查它是否包含 Any 类型的值。据我了解,它来自 SeqLike
, ,但会导致一些问题。
例如,我正在匹配 joda.DateTime 的小时数:
DateTime.now match {
case d if 0 to 12 contains d.hourOfDay() => ...
这里 d.hourOfDay() 返回 DateTime.Property,而不是 Int,但代码仍然可以编译,因为 contains(elem: Any)
. 。有什么方法可以在编译时检查此类调用吗?
解决方案
你可以 pimp Range
添加一个类型 - 更安全的方法:
class SafeRange( range: Range ) {
def safeContains( i: Int ) = range contains i
}
object SafeRange {
implicit def safer( range: Range ) = new SafeRange( range )
}
.
在任何范围实例上导入隐式和呼叫生成generacicetagcode:
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
. 其他提示
您可以使用 Scalaz 的类型安全等于 (===
) 和这个结合 exists
方法上 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" }
^
基于 Range 的 scaladocs 看起来没有更好的 Range 方法可以使用。你的选择似乎是
使用显式类型签名:
case d if 0 to 12 contains (d.hourOfDay(): Int) => ...
制定自己的方法:
def containsInt(r: Range, i: Int) = ...
这似乎是 Java 的遗留物 equals
是预泛型,这只是这一事实给 Scala 带来的不便之一。
不隶属于 StackOverflow