- [[.:prplreference| PRPL reference]] <- [[.:prplreference#lists|Lists]]
===== CopyList vs DeepCopyList vs dup / just passing the list =====
When you have a list in a variable for example, and you need to use the list in a function for example, you might not know whether to just pass the list into the funtion (<-myList @myFunction), use CopyList (<-myList CopyList @myFunction) or whether to use DeepCopyList (<-myList DeepCopyList @myFunction). In this article, you will learn the benefits and dangers of each.
=== Lists are the only mutable data type in PRPL ===
All other data types in PRPL (int, float and string) are immutable, that means that they never change their value. If you have number ''5'' stored in a variable ''x'' and call **<-x 1 add ->x,** you don't change the number ''5'' itself, you change the //content of variable ''x''// from ''5'' to ''6''.
Same with strings. If you call **<-myString "e" "a" StringReplace ->myString** you don't change the string //itself// that is stored in myString, you change //which// string is stored in myString. (If this doesn't make any sence to you, don't worry, the distinction will become clearel once we get to some examples with lists.)
However, with lists it's different. If you have a list stored in a variable myList and call **<-myList "foo" AppendToList** you are actaully //changing the list// stored inside the variable myList. You can, of course, still change //which// list is stored in a variable by calling **CreateList ->myList** for example. However, the fun becomes when the same list is stored in different varaibles.
=== Sharing list in multiple variables (or on stack) ===
Let's start by a quick example with 3 lists and 4 variables: (I have named the lists ListA,B,C so that we can keep track of which variable has which list stored in it)
"a,b,c" "," Split ->list1 #ListA
"a,b,c" "," Split ->list2 #ListB
<-list1 ->list3 #ListA
"x,y,z" "," Split ->list4 #ListC
<-list1 Trace # ["a", "b", "c"] #ListA
<-list2 Trace # ["a", "b", "c"] #ListB
<-list3 Trace # ["a", "b", "c"] #ListA
<-list4 Trace # ["x", "y", "z"] #ListC
This would make it seem that all the 3 variables list1,2,3 contain the same list, but they don't. list1 and list3 contain the same list, however list2 contains a different list, although with the same content as the list stored in list1 and list3.
If we change list1, list3 will be change as well, because it is the same list, just stored inside 2 different variables:
<-list1 2 "foo" SetListElement #ListA
<-list1 Trace # ["a", "b", "foo"] #ListA
<-list2 Trace # ["a", "b", "c"] #ListB
<-list3 Trace # ["a", "b", "foo"] #ListA
<-list4 Trace # ["x", "y", "z"] #ListC
However, if we change //which// list is stored inside the list1 variable, list3 will remain the same:
<-list4 ->list1 #ListC
<-list1 Trace # ["x", "y", "z"] #ListC
<-list2 Trace # ["a", "b", "c"] #ListB
<-list3 Trace # ["a", "b", "foo"] #ListA
<-list4 Trace # ["x", "y", "z"] #ListC
Now, the variables list1 and list4 contain the same list, and if we called **<-list1 "boo" AppendToList** for example, it would change list4 as well, because AppendToList changes the list itself, and list4 now contains the same list as list1.
=== Finally we get to use (Deep)CopyList ===
So, what if we didn't want 2 variables sharing the same list, but instead wanted to copy the list from one variable into another so that we can then change eighter list without affecting the other one? Well, that's //exactly// what CopyList is for. It creates a new list, but with the same contents.
"x,y,z" "," Split ->list1
<-list1 CopyList ->list2
<-list1 2 RemoveListElement
<-list1 Trace # [ "x", "y" ]
<-list2 Trace # [ "x", "y", "z" ]
And that's prety much it. [[.:DeepCopyList|DeepCopyList]] is for when the list being copied contains another lists as it's elements, so that even those lists gets copied instead of being shared. For even more datailed explanation with pictures, check out [[.:HowAreListsImplemented|How are lists implemented]].