17

我对 Scala 列表中的模式匹配有点困惑。

例如。

    val simplelist: List[Char] = List('a', 'b', 'c', 'd')

    //> simplelist  : List[Char] = List(a, b, c, d)

    def simple_fun(list: List[Char]) = list match {
           case (x:Char) :: (y:List[Char]) => println(x)
           case _ => Nil
     }                                                 
   //> simple_fun: (list: List[Char])Any

   simple_fun(simplelist)                            

   //> a
   //| res0: Any = ()

这当前只打印一行输出。它不应该在 List 的每个元素上运行/模式匹配吗?

编辑:我修复了编译错误并复制了 REPL 的输出。

4

3 回答 3

26

Unless you are repeatedly calling simple_fun in some way, what you have there will pattern match the first element and nothing more. To get it to match the whole list, you can get simple_fun to call itself recursively, like this:

val simplelist: List[Char] = List('a', 'b', 'c', 'd')

def simple_fun(list: List[Char]): List[Nothing] = list match {
  case x :: xs => {
    println(x)
    simple_fun(xs)
  }
  case _ => Nil 
}

Note I've also left out some of the types as the Scala compiler can infer them, leaving you with less cluttered, more readable code.

As a small side-note, calling println repeatedly inside the function like that is not particularly functional - as it is all about side effects. A more idiomatic approach would be to have the function construct a string describing the list, which is then output with a single call to println - so the side-effects are kept in a single well-defined place. Something like this would be one approach:

def simple_fun(list: List[Char]):String = list match {
  case x :: xs => x.toString + simple_fun(xs)
  case Nil => ""
}

println(simple_fun(simple_list))
于 2012-10-24T21:04:40.037 回答
6

I would also like to mention that the case for lists can be divided not only the head and tail, as well as any N number of list elements:

def anyFunction(list: List[Int]): Unit =
  list match {
        // ...methods that have already been shown
      case first :: second :: Nil  => println(s"List has only 2 elements: $first and $second")
      case first :: second :: tail => println(s"First: $first \nSecond: $second \nTail: $tail")
  }

Hope it will be useful to someone.

于 2019-07-21T17:02:42.623 回答
2

我认为以下应该有效:

def flatten(l: List[_]): List[Any] = l match {
  case Nil => Nil
  case (head: List[_]) :: tail => flatten(head) ::: flatten(tail)
  case head :: tail => head :: flatten(tail)
}

第一行是 Nil 的匹配项,所以如果我们没有找到任何内容,则什么也不返回。第二行将识别 List of Lists 并调用 flatten 方法并展平列表列表。

于 2016-07-31T17:17:53.410 回答