score:24

Accepted answer

The documentation says If this is empty then it does nothing and returns that. Otherwise, appends that to this.. That is exactly, what you observed. If you really need a mutable list, I would suggest you to use scala.collection.mutable.ListBuffer instead, with it you can do

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)

score:3

As I understand it is related to First/Last (Nil) element in the list (if list is empty Nil is first and last element at the same time).

LinkedList (still) follows "primitive charm" strategy. So it does not try to add/append new data to/after Nil, to have possible result like this: {Nil, newElement}. (After all Nil should be last element)

Of course it could check if list is empty then put addingList to the beginning and Nil to the end. But this would be "too smart", I guess.

But, anyway append() returns "expecting" result Like this:

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

result = {"a", "b"}. In this case it returns 'addingList' itself, and/but does not change initial list.

If we try to assign newElement to the next ref:

   emptyList.next = LinkedList("whatever")

As result we would have emtyList changed like this:

 LinkedList(null, whatever)

I.e. it creates fist element as null, since we have used next() assigning new/next element to it. So it moves Nil to the end, because first element which is null, has next reference to new element we added (addingElelement).

Because

"the "emptyList" is also the "head" link"

and head in our case head is Nil, but Nill can not have next, so it has to create new first element (which is has null value) with next() referece to our new addingElelement.

Personally I find it "too much primitive" and not "so much elegant". But it depends, I guess.

Task oriented story:

For my initial task (why I start thinking about this 'strange' list behaviour [even though it's mutable]) -- I wanted to use mutable list for a class/object called Dictionary which would keep Words in it (dictionary by default has not any words). And I would have methods like addWord(wod:String) for adding new words. For now my implementation will be changed (I'm not going to use this LinkedList, but rather MutableList. It seems it is more mutable than previous one):

object Dictionary {

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

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

}

But possible implementation could be like this:

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) )
    }

  }

}

But then I have to use var instead of val, and I should transform every new Word to LinkedList, and my logic became more complicated.


Related Query

More Query from same tag