【问题标题】:Scala Pattern Matching Error, "bad simple pattern: bad use of _* (sequence pattern not allowed)"Scala 模式匹配错误,“糟糕的简单模式:错误使用 _*(不允许序列模式)”
【发布时间】:2017-12-31 11:09:37
【问题描述】:

我在 Coursera 上写作业时遇到了一个关于 Scala 模式匹配的问题。

《Programming in Scala》一书有如下代码:

expr match { 
    case List(0, _ * ) => println("found it") 
    case _ => 
}

所以我写了一个类似的代码来计算列表中每个字符出现的频率:

/**
 * This function computes for each unique character in the list `chars` the number of
 * times it occurs. For example, the invocation
 *
 *   times(List('a', 'b', 'a'))
 *
 * should return the following (the order of the resulting list is not important):
 *
 *   List(('a', 2), ('b', 1)) */
 def times(chars: List[Char]): List[(Char, Int)] = {
   def addTime(char: Char, times: List[(Char, Int)]):List[(Char, Int)] = times match {
     case List(head @ (_*), (c , times), tail @ (_*)) if c == char => List(head, (c, times + 1), tail)
     case _ => List((char, 1))
 }

   if(chars.isEmpty) Nil else addTime(chars.head, times(chars.tail))
}

但是,编译器抱怨:

Error:(81, 29) bad simple pattern: bad use of _* (sequence pattern not allowed)
    case List(head @ (_*), (c , times), tail @ (_*)) if c == char => List(head, (c, times + 1), tail)

虽然我以另一种方式成功实现了这个方法,但在 2 个辅助函数的帮助下,我不知道为什么不允许这种序列模式。我试图谷歌,但我找不到答案。

任何建议将不胜感激。提前致谢。

【问题讨论】:

  • 我有点难以理解,你的代码应该表达什么,我想我终于找到了(带有 2 倍 '@' 符号的行):匹配某个位置的列表元组 (c, n) 有一个 c,匹配 (char)。我不太熟悉@-Syntax 及其用例,但从未见过像这样的头部和尾部的多重可变长度匹配 - 另外需要注意的是,数据结构不能保证只有一个匹配C。由于我怀疑您对 _* 更感兴趣 - 东西,我不发布我自己的解决方案(foldLeft + 模式匹配)
  • @userunknown 谢谢你,伙计。你说的正是我想要匹配的。原因是 _* 不允许在头部使用,正如您所建议的那样。

标签: scala pattern-matching


【解决方案1】:

任何模式匹配最多只能以一种方式分解原始值。如果case List(head @ (_*), (c , times), tail @ (_*)) 是合法的,它将允许headctimestail 的许多选项。您的意图似乎是按顺序尝试所有这些方式,并在守卫c == char 变为真时进行匹配,但这不是 Scala 模式匹配的工作方式。

实际上,为了简单起见,_* 只允许放在末尾。 List(_*, c) 之类的东西可以合理地允许,但事实并非如此。

【讨论】:

  • 非常感谢!我的错误是按照您的建议将 _* 放在首位。又看了一遍模式匹配的章节,有一句话:“如果你想对一个序列进行匹配而不指定它可以多长,你可以指定_*作为模式的最后一个元素。”
猜你喜欢
  • 2015-01-12
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 2014-02-05
  • 2012-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多