【发布时间】:2014-12-16 07:17:49
【问题描述】:
以下面的例子为例,为什么提取器被多次调用,而不是临时存储第一次调用的结果并与之匹配。假设unapply 的结果在给定相同字符串的情况下不会改变是不是很合理。
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")
}
【问题讨论】:
-
一般来说,判断一个函数是否是纯函数是不可能的。例如,参见stackoverflow.com/questions/11620395/side-effects-in-scala。鉴于(我认为)记录了按顺序检查案例,有可能(但风格很差)编写一个依赖副作用的 unapply。
-
@Paul:但是关于如何在匹配语句中使用提取器的规范可以被设计为允许这种优化,即使它们是可观察的关于有副作用的提取器。所以这个问题仍然存在。
-
是的,但不是这里有两个不同的问题——我相信,问的一个是,为什么编译器今天不优化这个,答案是因为它不能证明unapply 是纯粹的,规范并没有禁止 unapply 有副作用。如果问题是“是否可以更改语言规范以允许这种优化”,那么答案显然是肯定的。但这不是问的问题
-
加油!关于以“spec sais so”开头和结尾的编程语言设计的问题的答案是一个非常糟糕的答案。为什么规范是这样的?我也想知道!
-
Scala 中的很多东西都是这样的,因为 Scala 最初是作为改进的 Java 设计的,重点是 Java 兼容性。因此,特别是早期的特性被指定为与惯用的 Java “玩得很好”,即具有副作用的代码。 @som-snytt 的回答告诉我们,新特性的指定方式不同,因此规范保持这种方式可能更多是因为兼容性,而不是因为这是当今 Scala 社区的最佳权衡。