Scala добавить к изменяемому LinkedList

Пожалуйста, проверьте это

import scala.collection.mutable.LinkedList

var l = new LinkedList[String]

l append LinkedList("abc", "asd")

println(l)
// prints 
// LinkedList()

но

import scala.collection.mutable.LinkedList

var l = new LinkedList[String]

l = LinkedList("x")
l append LinkedList("abc", "asd")

println(l)
// prints 
// LinkedList(x, abc, asd)

Почему второй фрагмент кода работает, но первый не работает? Это находится на Scala 2.10

Ответы

Ответ 1

В документации указано If this is empty then it does nothing and returns that. Otherwise, appends that to this.. Это именно то, что вы наблюдали. Если вам действительно нужен измененный список, я бы предложил вам использовать scala.collection.mutable.ListBuffer, а с ним вы можете сделать

val lb = new ListBuffer[Int]

scala> lb += 1
res14: lb.type = ListBuffer(1)

scala> lb
res15: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1)

scala> lb ++= Seq(1,2,3)
res17: lb.type = ListBuffer(1, 1, 2, 3, 1, 2, 3)

scala> lb
res18: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 1, 2, 3, 1, 2, 3)

Ответ 2

Как я понимаю, это связано с элементом First/Last (Nil) в списке (если список пуст Nil - это первый и последний элемент одновременно).

LinkedList (по-прежнему) следует " примитивный шарм. Поэтому он не пытается добавлять/добавлять новые данные в/после Nil, чтобы иметь следующий результат: {Nil, newElement}. (В конце концов, Nil должен быть последним элементом)

Конечно, можно проверить, что список if пуст, а затем положить addingList в начало и Nil до конца. Но это было бы "слишком умно", я думаю.

Но, во всяком случае append() возвращает результат "ожидающий". Вот как:

val addingList = new LinkedList[String]("a", "b")
val result = emptyList append addingList

result = {"a", "b"}. В этом случае он возвращает сам 'addList' и /, но не меняет начальный список.

Если мы попытаемся присвоить newElement next ref:

   emptyList.next = LinkedList("whatever")

В результате мы бы изменили emtyList следующим образом:

 LinkedList(null, whatever)

т.е. он создает кулачный элемент как null, так как мы использовали next() назначение ему нового/следующего элемента. Поэтому он перемещает Nil до конца, потому что первый элемент, который имеет значение null, имеет следующую ссылку на добавленный новый элемент (addingElelement).

Потому что

"emptyList" также является "главной" ссылкой

и голова в нашем случае head Nil, но Nill не может быть следующей, поэтому он должен создать новый первый элемент (который имеет нулевое значение) со следующей() рефери к нашей новой addingElelement.

Лично я считаю его "слишком примитивным", а не "настолько элегантным". Но это зависит, я думаю.

Задача:

Для моей начальной задачи (почему я начинаю думать об этом "странном" поведении списка (хотя это изменено). Я хотел использовать измененный список для класса/объекта с именем Dictionary, который сохранил бы Words в он (словарь по умолчанию не имеет слов). И у меня были бы методы вроде ddWord(wod:String) для добавления новых слов. На данный момент моя реализация будет изменена (я не буду использовать этот LinkedList, а скорее MutableList. Похоже, что более изменчивый, чем предыдущий):

object Dictionary {

  val words = new mutable.MutableList[Word]();

  def addWord(word: Word): Unit = {
    words += word;
  }

}

Но возможная реализация может быть такой:

object Dictionary {

  var words = new mutable.LinkedList[Word]();

  def addWord(word: Word): Unit = {

    if (words.isEmpty) {
      words = words append( mutable.LinkedList[Word](word) ) // rely on append result
    } else {
      words append( mutable.LinkedList[Word](word) )
    }

  }

}

Но тогда я должен использовать var вместо val, и я должен преобразовать каждое новое Word в LinkedList, и моя логика усложнилась.