views:

298

answers:

5

How do you add an element to a List in Scala 2.7.5, without creating a new List and without using a deprecated solution.

+2  A: 

The += method on a list is deprecated because it adds an element to the tail, which is expensive. The least expensive way of adding an element to a list is to add to the head using ::=.

So the deprecation warning is a subtle hint that you should redesign your program to work by prepending instead of appending:

scala> var l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)

scala> l ::= 4

scala> l
res1: List[Int] = List(4, 1, 2, 3)

(Note that ::= and += on a var are not real methods, but sugar for l = l :: elem, etc)

Ben James
But is `l` still the same list? Also you are prepending, not appending.
leppie
Of course `l` is not the same list, lists are immutable.
Ben James
Well then you did not answer the question :)
leppie
Often the real solution to the underlying problem is not a direct answer to the original question.
Ben James
@leppie The questions asks how one adds an element. The question title mentions append. So he answered the question, though not the title. :-)
Daniel
@Daniel: No, he asked how to do it without creating a new list.
leppie
leppie, if you are aware of how Scala's syntactic sugar allows apparently mutable-style operations on immutable objects that are vars, then it makes sense to interpret that part of the question as "without *explicitly* creating a new list". And in case he/she wasn't aware of that, I have mentioned it too.
Ben James
+4  A: 

It's worth pointing out that List has a very specific meaning in scala, which is not equivalent to the java.util.List interface. List is a sealed, abstract class representing a recursive data-structure which has a head and a tail. (There do exist Java list-like structures in scala, some of which are mutable.)

Scala's Lists are immutable; modifying a list in any way is not possible, although you can create a new list be prepending to an existing one (which gives a new object back). Even though they are immutable, the structure is no more expensive in terms of object creation than, say, appending to a java.util.LinkedList

The + method has been deprecated for good reason because it is inefficient; instead use:

val newList = theList ::: List(toAppend)

I suppose a different way would be to prepend with 2 reversals:

val newList = (toAppend :: theList.reverse).reverse

I doubt this is any more efficient! In general, if I want append behaviour, I use prepend and then reverse (at the point of needing to access the list):

val newList = toAppend :: theList
//much later! I need to send the list somewhere...
target ! newList.reverse
oxbow_lakes
This is an argumentation, why the question might be a bad one. But it doesn't answer the question.
Jens Schauder
It exactly answers the question. The questioner has asked how to add to a list without creating a new list. This is impossible! Perhaps you should expand on why you have downvoted my (correct) answer
oxbow_lakes
Jens, to apply your own reasoning, you have not answered the question either since it asks how to append to a `List`, not a `LinkedList` or `ListBuffer`, neither of which derive from `List`. (Yet your answer is still useful.)
Ben James
+1  A: 

This should do it: http://www.scala-lang.org/docu/files/api/scala/collection/mutable/SingleLinkedList.html#append%28This%29

Or this: http://www.scala-lang.org/docu/files/api/scala/collection/mutable/ListBuffer.html#%2B%3A%28A%29

The basic trick is to use a mutable List (or class with similiar functionality)

Jens Schauder
+8  A: 

You could use a ListBuffer, which provides constant time append:

val buffer = new scala.collection.mutable.ListBuffer[Int]
buffer += 1
buffer += 2
val list = buffer.toList
Fabian Steeg
+2  A: 

Non deprecated way of appending an element to a List in Scala 2.7.5?

That does not exist, and it will never exist.

How do you add an element to a List in Scala 2.7.5, without creating a new List and without using a deprecated solution.

Use :::

val newList = element :: oldList

Or, if list is a var,

list ::= element

It does not create a new List (though, it creates a new ::, also known as cons), and it adds an element to it.

If you want to append elements to a sequence without creating a new sequence, use a mutable data structure.

Daniel