How can I change the nil list?

You know this scene in Goodbye and Thanks to everyone for the fish, where Arthur is so insanely happy that he stops the waiter and demands to know: "Why is this food so good?" I am in such a situation. Scala seems to be doing what I want, but I don’t understand how this is done. Consider the following:

scala> var v = Nil:List[String]; v: List[String] = List() scala> v.length res38: Int = 0 scala> v ::= "Hello" scala> v.length res39: Int = 1 scala> Nil.length res40: Int = 0 

This is exactly what you hope for, but how does it happen?

Nil is an object that extends List [Nothing], which is a subtype of List [String], so the assignment works fine, but it's an immutable list, isn't it? Therefore, I could not add it. But I can add to it, or at least I can add to v, which I thought points to Neil. v is changing, but Nil is not.

So, WTF? Does Scala have any clever copy-on-modification semantics that I don't know about? Is Nil really a function that returns empty lists? More broadly, is there any way to get the REPL to answer these questions?

+6
scala
source share
4 answers

When Scala sees

 v ::= "Hello" 

first checks to see if v knows the ::= method. In this case ( List type) this is not so, because the method consists only of characters and ends with the = sign, it tries something else:

 v = v.::("Hello") 

which, by the way, is spelled "Hello" :: v in infix notation. Now, since v knows the :: method, it works and returns a new List , which is then assigned to v , as indicated.

By the way, this is an addition, not an addition.

+16
source share

When you use the var keyword, you do not translate to final in the sense of Java. Instead, var allows you to remap. When you call the ::= operator, you are actually reassigning what v indicates. The ::= operator returns a new list, not the original list with "Hello" attached to it. Therefore, v now points to "Hello", and not to the Nil list.

See this here:

 var myThing = new List(1, 2, 3) var myOhterThing = myThing myThing = new List(1, 2, 3, 4) 

It's almost the same as saying: “Take the first list, copy it and add“ 4 ”to it. Now assign“ myThing ”to point to this list.” Using this operator, you did the same. Writing this method allows you to see it.

+4
source share

Try with val v to see whats mutable. :)

+3
source share

Nile is unchanged. When you are against this (: :), you get a new instance that is also immutable.

Try the following:

 val v1 = Nil val v2 = "Hello" :: v1 v1 == v2 

(you will get false since they do not point to the same object)

Given that v is var, you can reassign the values ​​for it.

So, when you have:

 v ::= "Hello" // what you really have is: v = "Hello" :: v // or v = "Hello" :: Nil // or v = List("Hello") 

The above creates a new list, and the Nil value remains unchanged. This is similar to adding String in Java. Since String is immutable, you never change one instance - only create new ones.

Since Nil has not changed, Nil.length = 0.

+2
source share

All Articles