gpt4 book ai didi

Scala - 添加 unapply 到 Int

转载 作者:行者123 更新时间:2023-12-04 07:42:09 26 4
gpt4 key购买 nike

我希望能够做到这一点:

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

但是 Int没有 unapply方法。

我找到了 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位于不同的命名空间中。

关于Scala - 添加 unapply 到 Int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9727236/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com