Имеет ли смысл использовать сопоставление с образцом в Scala с действительно простыми случаями? - PullRequest
7 голосов
/ 26 декабря 2011

В «Программирование в Scala, второе издание» на странице 410 вы можете найти класс Simulation , который имеет следующий метод:

private def next() {
  (agenda: @unchecked) match {
    case item :: rest =>
      agenda = rest
      curtime = item.time
      item.action()
  }
}

Мне любопытно, почему Одерский реализовал это с помощьюсопоставление с образцом, а не просто так:

private def next() {
  val item = agenda.head
  agenda = agenda.tail
  curtime = item.time
  item.action()
}

Является ли сопоставление с образцом настолько эффективным, что это вообще не имеет значения?Или это был просто не такой идеальный пример?

Ответы [ 4 ]

9 голосов
/ 26 декабря 2011

Обычно я бы написал так, как ты. (Несмотря на то, что сопоставление с образцом довольно эффективно, оно не так эффективно, как голова / хвост.) Вы бы использовали сопоставление с образцом, если

  1. Вы хотели попрактиковаться в сопоставлении с образцом
  2. Вы хотели MatchException вместо NoSuchElementException
  3. Вы собирались заполнить другие дела позже.
4 голосов
/ 26 декабря 2011

Есть несколько причин:

  1. Часть этой книги состоит в том, чтобы заставить вас думать в Scala (функциональных) терминах; сопоставление с образцом является функционально-программным эквивалентом.

  2. Сопоставление с образцом и функциональный подход являются естественным образцом в Scala и допускают такие вещи, как параллелизм естественным образом; изучите этот шаблон, и ваши программы Scala будут готовы к более сложному использованию.

3 голосов
/ 26 декабря 2011

Сопоставление с образцом более идиоматично в Scala и легче защищает вас от граничных условий.

В коде

private def next() {
  val item = agenda.head
  agenda = agenda.tail
  curtime = item.time
  item.action()
}

И agenda.head, и agenda.tail будут выбрасывать NoSuchElementException исключение, если agenda - пустой список, поэтому, чтобы он действительно работал, вам нужно добавить проверку для этого.

Версия сопоставления с образцом на самом деле имеет похожую проблему (как отмечено в th комментариях),но я нахожу исправление, так как все, что вам нужно сделать, это добавить еще один шаблон:

private def next() {
  (agenda: @unchecked) match {
    case item :: rest =>
      agenda = rest
      curtime = item.time
      item.action()
    case _ => {}
  }
}
0 голосов
/ 15 января 2017

Во-первых, я предполагаю, что исключения не являются проблемой, возможно, есть некоторая проверка перед вызовом этого «следующего» метода. На самом деле, это, вероятно, и является причиной «неконтролируемой» аннотации, поэтому ему действительно может не понадобиться добавлять дополнительные case _ =>. Я думаю, что аргументация была больше в том, что он хотел использовать «неприменить». Альтернативой здесь без сопоставления с образцом, но также без head и tail может быть что-то вроде:

private def next() {  
    val item :: rest = agenda
    agenda = rest
    curtime = item.time
    item.action()
}
...