Сопоставление шаблонов в списке в Scala

Я немного смущен относительно соответствия шаблонов в списке в 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 = ()

В настоящее время выводится только одна строка вывода. Должно ли оно не запускаться/соответствие шаблону для каждого элемента списка?

EDIT: Я исправил ошибки компиляции и скопировал вывод из REPL.

Ответ 1

Если вы несколько раз вызываете simple_fun каким-то образом, то, что у вас там, будет соответствовать совпадению первого элемента и не более того. Чтобы он соответствовал всему списку, вы можете получить simple_fun, чтобы вызвать его рекурсивно, например:

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 
}

Примечание. Я также отказался от некоторых типов, поскольку компилятор Scala может их вывести, оставив вас с менее загроможденным и более читаемым кодом.

Как маленькая заметка, вызов println многократно внутри функции, подобной той, что не особенно функциональна, поскольку речь идет о побочных эффектах. Более идиоматический подход состоял бы в том, чтобы функция построила строку, описывающую список, который затем выводится с одним вызовом на println, поэтому побочные эффекты хранятся в одном четко определенном месте. Что-то вроде этого будет одним из способов:

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

println(simple_fun(simple_list))

Ответ 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, поэтому, если мы ничего не найдем, ничего не получим. Вторая строка идентифицирует список списков и вызовет метод сглаживания и сгладит список списков.

Ответ 3

Также хотелось бы отметить, что падеж для списков можно разделить не только на голову и хвост, но и на любое количество элементов списка N:

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")
  }

Надеюсь, это будет кому-то полезно.