dhg*_*dhg 8 scala implicit-conversion unapply
我希望能够这样做:
scala> val Int(i) = "1"
i: Int = 1
Run Code Online (Sandbox Code Playgroud)
但是Int没有unapply方法.
我找到了这个答案,它给出了如何隐式地将方法添加到现有对象的说明,所以我试了一下.他们提供的解决方案有效,但遗憾的是不适用于模式匹配.这就是我所拥有的:
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
Run Code Online (Sandbox Code Playgroud)
这些测试用例都很好:
val UnapplyInt(i) = "1" // pattern matching with unapply is fine
val i = Int.unapply("1").get // implicit conversion is fine
Run Code Online (Sandbox Code Playgroud)
但我想要的那个失败了:
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"
^
Run Code Online (Sandbox Code Playgroud)
如果隐式转换工作和模式匹配unapply工作,为什么Scala不将这两个东西放在一起用于隐式模式匹配?
编辑所以我原来的推理并不好.真正的原因来自Scala语言规范的8.1.8节
Syntax:
SimplePattern ::= StableId ‘(’ [Patterns] ‘)’
Run Code Online (Sandbox Code Playgroud)
也就是说,提取器对象必须是稳定的,并且隐式转换不稳定.没有解释为什么提取器必须稳定; 我怀疑这是因为Scala不想将提取器视为表达式,因为这很快就会变得模棱两可:
... match {
foo(bar)(baz)
}
Run Code Online (Sandbox Code Playgroud)
现在哪个是构造函数,哪个是模式变量?
幸运的是,你可以做到这一点,它工作得很好(但,正如你评论,引入其他问题):
object Int {
def unapply(v: String) = try Some(v.toInt)
catch { case _: NumberFormatException => None }
}
val Int(i) = "5"
Run Code Online (Sandbox Code Playgroud)
因为类型Int和对象Int在不同的名称空间中.
| 归档时间: |
|
| 查看次数: |
1153 次 |
| 最近记录: |