2

Take the following example, why is the extractor called multiple times as opposed to temporarily storing the results of the first call and matching against that. Wouldn't it be reasonable to assume that results from unapply would not change given the same string.

object Name {
  val NameReg = """^(\w+)\s(?:(\w+)\s)?(\w+)$""".r

  def unapply(fullName: String): Option[(String, String, String)] = {
    val NameReg(fname, mname, lname) = fullName
    Some((fname, if (mname == null) "" else mname, lname))
  }
}

"John Smith Doe" match {
  case Name("Jane", _, _) => println("I know you, Jane.")
  case Name(f, "", _) => println(s"Hi ${f}")
  case Name(f, m, _) => println(s"Howdy, ${f} ${m}.")
  case _ => println("Don't know you")
}
4

2 回答 2

1

假设在unapply给定相同字符串的情况下结果不会改变,这不是合理的吗?

不幸的是,假设对于(静态)编译器来说还不够好。为了使记忆成为合法的优化,编译器必须证明被记忆的表达式是纯粹的并且是引用透明的。但是,在一般情况下,这相当于解决了停机问题。

当然可以编写一个优化过程,试图证明某些表达式的纯度并记住它们,当且仅当它成功时,但这可能比它的价值更麻烦。这样的证明很快就会变得非常困难,因此它们只可能在非常琐碎的表达式上成功,无论如何执行都非常快。

于 2014-12-16T11:17:21.233 回答
0

什么是模式匹配?规范说它匹配值的“形状”并将 vars 绑定到它的“组件”。

在突变领域,你有这样的问题,如果我匹配 on case class C(var v: V),是否case C(x)捕获可变字段?好吧,答案是否定的:

https://issues.scala-lang.org/browse/SI-5158

规范说(对不起)评估顺序可能会改变,所以它建议不要产生副作用:

为了提高效率,模式匹配表达式的评估可能会以文本序列以外的其他顺序尝试模式。这可能会通过警卫中的副作用影响评估。

这与保护表达式有关,大概是因为提取器是在案例类之后添加的。

没有特别承诺只评估一次提取器。(即在规范中明确表示。)

语义只是“按顺序尝试模式”。

此外,您的正则表达式示例可以简化,因为当正则表达式未应用于其自己的匹配时,不会重新评估。请参阅文档中的示例。那是,

Name.NameReg findFirstMatchIn s map {
  case Name("Jane",_,_) =>
}

在哪里

object Name { def unapply(m: Regex.Matcher) = ... }
于 2014-12-16T17:25:13.230 回答