如果后卫没有编译,正则表达式无法理解

时间:2017-07-26 17:35:38

标签: scala

为什么以下内容无法编译

for {
    s <- List.empty[String]
    regex <- List.empty[scala.util.matching.Regex]
    regex(ss) = s
    if ss == "foo"
} yield s

但删除了if

for {
    s <- List.empty[String]
    regex <- List.empty[scala.util.matching.Regex]
    regex(ss) = s
} yield s

或重新排列for comprehension中两个列表的顺序

for {
    regex <- List.empty[scala.util.matching.Regex]
    s <- List.empty[String]
    regex(ss) = s
    if ss == "foo"
} yield s

编译?

Scalafiddle:http://scalafiddle.net/console/2519ff98d434cb522589f54a9c5fcf55

2 个答案:

答案 0 :(得分:2)

您可以使用以下命令查看翻译的for-comprehension:

scalac -Xprint:all <file>.scala

在您的第一个示例中,生成的代码如下所示(我稍微清理了输出):

List.empty[String]
  .flatMap(((s) =>
    List.empty[scala.util.matching.Regex]
      .map(regex => {
        private[this] val x$2 =
        s match {
          case (x$1@regex((ss@_))) => scala.Tuple2(x$1, ss)
        };
        val x$1 = x$2._1;
        val ss = x$2._2;
        scala.Tuple2(regex, x$1)
      }).withFilter((x$3 => x$3 match {
      case scala.Tuple2((regex@_), regex((ss@_))) => ss.$eq$eq("foo")
    })).map(((x$4) => x$4 match {
      case scala.Tuple2((regex@_), regex((ss@_))) => s
    })))
  )

问题似乎是withFilter子句在regex(ss)语句中直接使用表达式case,但在那里没有定义值regex。我不确定这是否可以被视为语言规范或编译器中的缺陷。错误信息当然不是很有帮助。

您可以阅读Scala language specification的第6.19章中的详细信息。

答案 1 :(得分:-2)

这可能会对你有帮助。

 import scala.util.matching.Regex
 import scala.util.control.Exception._



for {
    s <- List.empty[String]
    regex <- List.empty[scala.util.matching.Regex]
    ss <- extract(regex, s)
    if ss == "foo"
  } yield s



def extract(regex: Regex, s: String): Option[String] = allCatch.opt {
    val regex(ss) = s
    ss
  }