Что здесь происходит с scala.collection.immutable.Stack. +: (Prepend)? - PullRequest
4 голосов
/ 18 октября 2011

Я заметил, что ScalaDoc для неизменяемого стека относится к методу, предваряющему следующую подпись:

class Stack[A+] ...
  def +: (elem: A): Stack[A]

Эта сигнатура метода выглядела неправильно для меня, поскольку стек является ковариантным в параметре типа A (поэтомуэлемент должен быть ошибкой компилятора).Более того, Scaladoc говорит, что определение этого метода в GenSeqLike, но его там нет.

В SeqLike есть реализация +: я думаю, что именно она используется в Stack.

trait SeqLike[+A, +Repr] ...
  def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
    val b = bf(repr)
    b += elem
    b ++= thisCollection
    b.result
  }

Это выглядит не так эффективно, как Stack.push.

Когда я пытаюсь предоставить собственную реализацию +: (как push), я получаю ожидаемый компиляторошибок, которых нет в методе, который я переопределяю, и о проблеме ковариации.

class Stack2[+A] extends Stack[A] {
  override def +: (elem: A): Stack[A] = this push elem
}

scalac Stack2.scala дает:

Stack2.scala:4: error: method +: overrides nothing
  override def +: (elem: A): Stack[A] = this push elem
               ^
Stack2.scala:4: error: covariant type A occurs in contravariant position in type A of value elem
  override def +: (elem: A): Stack[A] = this push elem
                   ^
two errors found

Возможно ли реализовать +: эффективноиспользуя толчок?

1 Ответ

7 голосов
/ 18 октября 2011

Документация здесь немного запутанная. Вы заметите, что этот метод помечен как сценарий использования . Фактическая подпись такая:

def +: [B >: A, That] (elem: B)(implicit bf: CanBuildFrom[Stack[A], B, That]): That
Prepends an element to this immutable stack

Вариант использования просто показывает типичный способ его использования (и хотя действительная подпись изменилась в SeqLike, сценарий использования не изменился с GenSeqLike, отсюда и явно неправильная атрибуция).

Вы правы, что реализация +: неэффективна, хотя вы не можете сказать это наверняка, учитывая код, который вы опубликовали. b ++= thisCollection может заметить, что все остальное - просто стек, и нажать elem спереди. Но это не так; b это просто ArrayBuffer под капотом.

Так что используйте вместо этого список, как подсказывает документ.

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