Simple (I think) List Question

I can’t believe I have never run into this before. I want to take a list, copy it to another variable, possibly make some changes to that second list then compare them and perform an task if the lists are different. When I make changes to the second list, it is also changing the first list. Here is sample code of what I am trying to ask:

set theList to {"Dog", "Cat", "Fish"}
set copyList to theList
set item 1 of copyList to "Horse"
return theList

This returns a list of {“Horse”, “Cat”, “Fish”} for theList, even though I told the script to change the copyList variable. I’m sure this is just something stupid that I should already know, but I havent’ been able to figure it out. Any help for a scripter who probably shouldn’t really need help with something like this by now?

That always happens, as soon as I post something I figure it out. Still would be curious for an answer as to why it does that as posted above, but this fixed it.

set theList to {"Dog", "Cat", "Fish"}
set copyList to the items of theList as list
set item 1 of copyList to "Horse"
return theList

Hello.

That would be because since a list is a mutable structure, you only get a reference to to the item when you set it.
This should also happen with records. If you are familiar with any other language like “C”, you can view a list as an array, which really is only a contiguous block of memory, where you access its element by adding an offset according to the index element to its base address. It is kind of like this with lists too.

What I’m really trying to communicate, is that it is much more convenient and much faster for applescript to pass you a reference than to copy the whole thing to you. -It would take a great amount of time to do this with every list, since you not only have to copy the values, but you must also give them a new base address for reference, (that would be though a vector table, for looking up the values in the list.

Be aware of though, that a copy operation performs a deep copy, i.e it copies the surrounding environment to the list if it is a global property, if you perform such an operation in a loop, this may lead to
loss of memory, because every time you perform the copy, all the memory of the running script are copied with it.
Also any previous value of the property, with its surrounding environment.(Cascading).

Hopes this helps and makes some sense.

Best Regards

McUsr

When you set one variable to another, they both point to (or contain) the same object. If the object is some kind of container or structure (list, record, or date) and you change its contents, you’ll see the changes whichever variable you use to look at it.

When you set the variable to something else ” such as the result of extracting all the items of class ‘item’ from the list ” you get a different list. However, this list contains the same physical items as the first. You can put different items in one list and the other list will remain as it was. But it any of the items are themselves containers, and you simply change their contents, you’ll see the changes in both lists.

set theList to {"Dog", "Cat", "Fish", {"Aardvark"}}
set copyList to the items of theList
set item 1 of copyList to "Horse"
return theList --> {"Dog", "Cat", "Fish", {"Aardvark"}}

-- But:
set theList to {"Dog", "Cat", "Fish", {"Aardvark"}}
set copyList to the items of theList
set item 1 of item 4 of copyList to "Horse"
return theList --> {"Dog", "Cat", "Fish", {"Horse"}}

When you copy one variable to another, structural objects are duplicated. What McUsr refers to as a “deep copy” means that every structure within the structure is duplicated, not just the top-level item. You can thus change anything at all within one structure without affecting anything in the other:

set theList to {"Dog", "Cat", "Fish", {"Aardvark"}}
copy theList to copyList -- Duplicate the entire structure.
set item 1 of item 4 of copyList to "Horse"
return theList --> {"Dog", "Cat", "Fish", {"Aardvark"}}

I don’t know what McUsr means by copying “the surrounding environment” and “if it is a global property”. A “deep copy” is the duplication of the internal structure. Only variables have scope. Copy and set work on values, which don’t.

Hello.

That was my basic idea of it too (and a property can hold an object - right?), apparently under some circumstances a copy command performs in some “closureish” way.

That was what I learned from this thread at Apple Discussions

I think Hiroto sums it up quite nicely in his post in that thread:

And this perplexed me. Because this implies that a copy command can perform like some closure. :smiley:

If you set a property which is referenced by an object before you assign that object to a variable you also create a closure. -The copy command on the other hand saves everything, which would have been needed to perform a closure. :smiley:

@Original Poster :slight_smile: Don’t let this scare you, this is stuff you seldom stumble upon.

Best Regards

McUsr

Thanks for the replies. I think I get what was going on now.

I’ve been doing this for a couple years now and haven’t run into anything quite like this one, so I wasn’t too worried. I was just curious what the deal was.

Thanks again…

The issue in that case was specifically that the object being copied ” several times ” was a compiled script object. It’s not relevant here unless you mention that fact.

Hello.

I had it in mind, but I didn’t mention it. So I guess we can agree upon that copy has side effects when copying global script objects iteratively? :slight_smile:

This really perplexed me.

Best Regards

McUsr