运维开发网

Scala – 向Int添加unapply

运维开发网 https://www.qedev.com 2020-05-15 15:11 出处:网络 作者:运维开发网整理
我希望能够做到这一点: scala> val Int(i) = "1" i: Int = 1 但Int没有一个不适用的方法. 我找到了this answer,它提供了如何隐式地将方法添加到现有对象的说明,所以我试了一下.他们给出的解决方案有效,但遗憾的是不适用于模式匹配.这就是我所拥有的: object UnapplyInt { val IntRE = """^(\d+)$""".r de
我希望能够做到这一点:

scala> val Int(i) = "1"
i: Int = 1

但Int没有一个不适用的方法.

我找到了this answer,它提供了如何隐式地将方法添加到现有对象的说明,所以我试了一下.他们给出的解决方案有效,但遗憾的是不适用于模式匹配.这就是我所拥有的:

object UnapplyInt {
  val IntRE = """^(\d+)$""".r
  def unapply(v: String): Option[Int] = v match {
    case IntRE(s) => Some(s.toInt)
    case _ => None
  }
}
implicit def int2unapplyInt(objA: Int.type) = UnapplyInt

这些测试用例都很好:

val UnapplyInt(i) = "1"       // pattern matching with unapply is fine
val i = Int.unapply("1").get  // implicit conversion is fine

但我想要的那个失败了:

scala> val Int(i) = "1"
<console>:10: error: object Int is not a case class constructor, nor does it have an unapply/unapplySeq method
       val Int(i) = "1"
           ^

如果隐式转换工作和与unapply的模式匹配有效,为什么Scala不将这两个东西放在一起用于隐式模式匹配?

编辑所以我原来的推理并不好.真正的原因是从 Section 8.1.8 of the Scala language spec

Syntax:
    SimplePattern ::= StableId ‘(’ [Patterns] ‘)’

也就是说,提取器对象必须是稳定的,并且隐式转换不稳定.没有解释为什么提取器必须稳定;我怀疑这是因为Scala不想将提取器视为表达式,因为这很快就会变得模棱两可:

... match {
    foo(bar)(baz)
}

现在哪个是构造函数,哪个是模式变量?

幸运的是,你可以做到这一点并且工作正常(但是,正如你评论的那样,引入了其他问题):

object Int {
    def unapply(v: String) = try Some(v.toInt)
        catch { case _: NumberFormatException => None }
}

val Int(i) = "5"

因为Int类型和对象Int位于不同的名称空间中.

0

精彩评论

暂无评论...
验证码 换一张
取 消