【问题标题】:Scala Range contains(elem: Any) methodScala Range contains(elem: Any) 方法
【发布时间】:2011-09-12 07:47:01
【问题描述】:

显然Range 有一个方法可以检查它是否包含任何类型的值。我知道它来自SeqLike,但会导致一些问题。

例如,我正在匹配 joda.DateTime 的小时数:

DateTime.now match {
    case d if 0 to 12 contains d.hourOfDay() => ...

这里 d.hourOfDay() 返回 DateTime.Property,而不是 Int,但代码仍然可以编译,因为 contains(elem: Any)。有没有办法在编译时检查此类调用?

【问题讨论】:

    标签: scala scalac


    【解决方案1】:

    您可以在 TraversableOnce 上将 Scalaz 的类型安全等于 (===) 与 exists 方法结合使用。

    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" }
                                 ^
    

    【讨论】:

      【解决方案2】:

      你可以pimpRange添加一个类型安全的包含方法:

      class SafeRange( range: Range ) {
        def safeContains( i: Int ) = range contains i
      }
      
      object SafeRange {
        implicit def safer( range: Range ) = new SafeRange( range )
      }
      

      导入隐式并在任何范围实例上调用safeContains

      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
      

      【讨论】:

        【解决方案3】:

        基于the scaladocs for Range,您似乎没有更好的 Range 方法可以使用。您的选择似乎是

        使用显式类型签名:

         case d if 0 to 12 contains (d.hourOfDay(): Int) => ...
        

        制作自己的方法:

         def containsInt(r: Range, i: Int) = ...
        

        这似乎是 Java equals 前泛型的遗留问题,并且只是这一事实给 Scala 带来的不便之一。

        【讨论】:

        • 是的......但也许应该有某种编译器警告调用这些方法。在类型安全的语言中出现这样的运行时错误似乎是错误的。
        • 我希望有一个能产生更多/更好警告的插件。有这种事吗?
        • @ziggystar 我不知道有一个。我不确定编译器是如何判断这不是你想要的,除了弃用该方法(这可能是正确的解决方案,但它还有其他问题......)
        • @Owen 在其他情况下我对 std lib 不满意,因为它很容易出错。见stackoverflow.com/questions/7040806/…
        猜你喜欢
        • 2011-08-22
        • 2013-08-06
        • 1970-01-01
        • 2020-04-04
        • 1970-01-01
        • 2015-10-06
        • 1970-01-01
        • 2017-11-28
        • 1970-01-01
        相关资源
        最近更新 更多