emi
emi

Reputation: 2950

Add element to a list In Scala

I'm running Scala 2.10.2. I want to create a list, then add some elements to the list and expect to see all the elements in the lists when I call the list's name. But I observed something quite weird (At least weird for me since I'm a newbie). Below is the what I tried to do in my sbt console

scala> val l = 1.0 :: 5.5 :: Nil
l: List[Double] = List(1.0, 5.5)

scala> l
res0: List[Double] = List(1.0, 5.5)

scala> l ::: List(2.2, 3.7)
res1: List[Double] = List(1.0, 5.5, 2.2, 3.7)

scala> List(l) :+ 2.2
res2: List[Any] = List(List(1.0, 5.5), 2.2)

scala> l
res3: List[Double] = List(1.0, 5.5)

scala> 

First, I created the list l with 2 elements (1.0 and 5.5). I call l and get what I expect; the two elements. Now I tried to add another element to the list using ::: which returned a new list with a new list of elements I added (2.2 and 3.7) Sweet! I even checked someone else's code for help: Appending an element to the end of a list in Scala to use a new construct :+. So at this stage I'm all happy, but I call l and I get the unexpected: `res3: List[Double] = List(1.0, 5.5)'.

Where are the elements I added? And how do I add these elements correctly so that when I call l I get a new list with all the stuff I added?

Upvotes: 35

Views: 120343

Answers (4)

Rich Oliver
Rich Oliver

Reputation: 6109

You are using an immutable list. The operations on the List return a new List. The old List remains unchanged. This can be very useful if another class / method holds a reference to the original collection and is relying on it remaining unchanged. You can either use different named vals as in

val myList1 = 1.0 :: 5.5 :: Nil 
val myList2 = 2.2 :: 3.7 :: mylist1

or use a var as in

var myList = 1.0 :: 5.5 :: Nil 
myList :::= List(2.2, 3.7)

This is equivalent syntax for:

myList = myList.:::(List(2.2, 3.7))

Or you could use one of the mutable collections such as

val myList = scala.collection.mutable.MutableList(1.0, 5.5)
myList.++=(List(2.2, 3.7))

Not to be confused with the following that does not modify the original mutable List, but returns a new value:

myList.++:(List(2.2, 3.7))

However you should only use mutable collections in performance critical code. Immutable collections are much easier to reason about and use. One big advantage is that immutable List and scala.collection.immutable.Vector are Covariant. Don't worry if that doesn't mean anything to you yet. The advantage of it is you can use it without fully understanding it. Hence the collection you were using by default is actually scala.collection.immutable.List its just imported for you automatically.

I tend to use List as my default collection. From 2.12.6 Seq defaults to immutable Seq prior to this it defaulted to immutable.

Upvotes: 46

Aaditya Shukla
Aaditya Shukla

Reputation: 21

Since you want to append elements to existing list, you can use var List[Int] and then keep on adding elements to the same list. Note -> You have to make sure that you insert an element into existing list as follows:-

var l: List[int] = List() // creates an empty list

l = 3 :: l // adds 3 to the head of the list

l = 4 :: l // makes int 4 as the head of the list

// Now when you will print l, you will see two elements in the list ( 4, 3)

Upvotes: 2

Yann Moisan
Yann Moisan

Reputation: 8281

I will try to explain the results of all the commands you tried.

scala> val l = 1.0 :: 5.5 :: Nil
l: List[Double] = List(1.0, 5.5)

First of all, List is a type alias to scala.collection.immutable.List (defined in Predef.scala).

Using the List companion object is more straightforward way to instantiate a List. Ex: List(1.0,5.5)

scala> l
res0: List[Double] = List(1.0, 5.5)

scala> l ::: List(2.2, 3.7)
res1: List[Double] = List(1.0, 5.5, 2.2, 3.7)

::: returns a list resulting from the concatenation of the given list prefix and this list

The original List is NOT modified

scala> List(l) :+ 2.2
res2: List[Any] = List(List(1.0, 5.5), 2.2)

List(l) is a List[List[Double]] Definitely not what you want.

:+ returns a new list consisting of all elements of this list followed by elem.

The type is List[Any] because it is the common superclass between List[Double] and Double

scala> l
res3: List[Double] = List(1.0, 5.5)

l is left unmodified because no method on immutable.List modified the List.

Upvotes: 8

Anthony Accioly
Anthony Accioly

Reputation: 22461

Use import scala.collection.mutable.MutableList or similar if you really need mutation.

import scala.collection.mutable.MutableList
val x = MutableList(1, 2, 3, 4, 5)
x += 6 // MutableList(1, 2, 3, 4, 5, 6)
x ++= MutableList(7, 8, 9) // MutableList(1, 2, 3, 4, 5, 6, 7, 8, 9)

Upvotes: 12

Related Questions