скала кейсы вопросы - PullRequest
       25

скала кейсы вопросы

8 голосов
/ 05 октября 2009

У меня есть два вопроса относительно класса дел ::.

:: можно использовать как

case head :: tail => ...

Как это работает? То есть, какой именно поток использует Scala для сопоставления экземпляра List с классом :: case? Учитывая, что у меня есть класс MyClass с оператором op, могу ли я создать класс case с именем op, который я могу использовать как:

case foo op bar => ....

Ответы [ 4 ]

5 голосов
/ 05 октября 2009
     scala> abstract class Stack {
     |     def push(n :Int):Stack
     | }
      defined class Stack

     scala> final case class push(st :Stack,hd :Int) extends Stack {
     |     override def push(n :Int):Stack = new push(this,n)
     | }
     defined class push

     scala> object NullStack extends Stack {
     |     override def push(n :Int):Stack = new push(null,n)
     | }
     defined module NullStack

     scala> val s = NullStack.push(1).push(2)
     s: Stack = push(push(null,1),2)

     scala> def test(s :Stack) = s match { case st push i => println(st +"push " + i) }
     test: (Stack)Unit

     scala> test(s)
     push(null,1)push 2
3 голосов
/ 06 октября 2009

Это подробно описано на странице 301 из Программирование в Scala , О сопоставлении с образцом на List с.

Шаблон "cons" x :: xs является частным случаем инфикса схема работы. Вы уже знаете, что, когда рассматривается как выражение, инфиксная операция эквивалентна вызову метода. Для моделей, правила различаются: если рассматривать как шаблон, инфиксную операцию, такую ​​как p op q эквивалентно op(p, q). То есть инфиксный оператор op обрабатывается как шаблон конструктора. В частности, шаблон минусов, такой как x :: xs, обрабатывается как ::(x, xs). Это намекает на то, что должен существовать класс с именем ::, который соответствует шаблону конструктор. Действительно есть такой класс. Он называется scala.:: и является именно тем классом, который создает непустые списки.

2 голосов
/ 06 октября 2009

На самом деле тот факт, что :: является классом case, - это только половина ответа. Причина, по которой это работает в сопоставлении с образцом, заключается в том, что для object :: существует extractor , который генерируется автоматически при определении класса case. Удобно, ::. Unapply возвращает список, потому что :: расширяет список. Если вы хотите использовать тот же трюк для списков, вы не сможете расширить список, потому что это final . Что вы можете сделать, это определить объект с помощью соответствующего неприменимого метода, который имеет ожидаемую подпись возврата. Например, чтобы соответствовать элементу last списка, вы можете сделать:

object ::> {def unapply[A] (l: List[A]) = Some( (l.init, l.last) )}

List(1, 2, 3) match {
  case _ ::> last => println(last)
}

(1 to 9).toList match {
  case List(1, 2, 3, 4, 5, 6, 7, 8) ::> 9 => "woah!"
}
(1 to 9).toList match {
  case List(1, 2, 3, 4, 5, 6, 7) ::> 8 ::> 9 => "w00t!"
}

Экстрактор должен возвращать Option, который содержит кортеж из двух деконструированных элементов.

0 голосов
/ 20 декабря 2010

Текст, цитируемый eed3si9n, находится на стр. 331 в PDF-издании «Программирование в Scala» (1-е изд.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...