Queue3 Глава 19 по программированию в Scala 2-е издание Вопрос - PullRequest
4 голосов
/ 02 сентября 2011

Я делаю обзор кода для примера Queue3 в издании Программирование в Scala 2 от Odersky et al. И я думаю, я застрял.

Вот код: http://booksites.artima.com/programming_in_scala_2ed/examples/type-parameterization/Queues3.scala

object Queues3 {
  class Queue[T](
    private val leading: List[T], 
    private val trailing: List[T] 
  ) {
    private def mirror = 
      if (leading.isEmpty)
        new Queue(trailing.reverse, Nil)
      else
        this

    def head = mirror.leading.head

    def tail = { 
      val q = mirror 
      new Queue(q.leading.tail, q.trailing) 
    }

    def enqueue(x: T) = 
      new Queue(leading, x :: trailing)
    override def toString = 
      leading ::: trailing.reverse mkString ("Queue(", ", ", ")")
  }

  object Queue {
    // constructs a queue with initial elements `xs'
    def apply[T](xs: T*) = new Queue[T](xs.toList, Nil)
  }

  def main(args: Array[String]) {
    val q = Queue[Int]() enqueue 1 enqueue 2
    println(q)
  }
}

Таким образом, он пытается реализовать очередь функциональным способом программирования со скоростью, аналогичной императивному.

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

leading ::: trailing.reverse

В книге говорится, что наихудший сценарий - это когда ведущий пуст.

Так что, если код сделать это

val q = Queue[Int]() enqueue 1 enqueue 2

Тогда, q.leading - это List (), а q.trailing - это List (2,1)

Поэтому, когда я вызываю q.head, в книге указывалось, что, поскольку ведущий пуст, зеркало копирует все из конечного, меняет его на обратное и устанавливает его в качестве ведущего.

Проблема в том, что я не думаю, что это работает, потому что это метод? Так что это не сохраняется через государство. Потому что я сделал открытыми свойства кода и проверил q.leading и q.trailing, и значение осталось прежним. Что я ожидаю после того, как сделаю q.head, так это:

q.leading is List(1,2) and q.trailing is List()

Но это не так, я что-то упустил? Это какая-то парадигма FP, которую я пропускаю? Потому что я думаю, что это может работать так, как я думаю, должно работать, если методы head и tail меняются на var.

Спасибо за ваше время.

Изменить, сделав свойства общедоступными:

частный Вэл ведущий: список [T], private val trailing: List [T]

редактирование: глава 19 в 1-м издании: http://www.artima.com/pins1ed/type-parameterization.html

1 Ответ

5 голосов
/ 02 сентября 2011

Ваша проблема в том, что методы head и tail не возвращают новые Queue. И вы осматриваете старый. Оформить заказ этой версии head и tail. Теперь они возвращают новый Queue в кортеже.

def head: (T, Queue[T]) = {
    val q = mirror
    (q.leading.head, q)
  }

def tail: (Queue[T], Queue[T]) = {
  val q = mirror
  (new Queue(q.leading.tail, q.trailing), q)
}

Как видите, mirror отлично работает.

val q = Queue[Int]() enqueue 1 enqueue 2
println(q)
printLT(q)
val q1 = q.head
println(q1._1)
printLT(q1._2)

def printLT[A](q: Queue[A]) {
  println("leading: " + q.leading)
  println("trailing: " + q.trailing)
}

Выход:

Queue(1, 2)
leading: List()
trailing: List(2, 1)
1
leading: List(1, 2)
trailing: List()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...