Bit by Scope/Reference Issue

I was bit by a scope/reference issue in a subroutine. I had assumed that using a subroutine, even with different variable names, would not modify the input value because the local scope of the variables inside and outside of the subroutine would not effect each other but I was wrong. Consider the following example:

In the first part of the script, using the “modify_the_list_contents” I get the desired results, a new modified list leaving the input list untouched. This is because I had to change the input value from a reference to the object’s contents to the actual contents. In the second value I don’t make this distinction and running the subroutine actually modifies the external value because it is using the reference. This is probably covered in depth somewhere but I just spent hours trying to solve a bug where my initial value was changing because of a subroutine that modified the reference instead of the contents (not what I wanted).

Just thought this might help someone…

Jon


[This script was automatically tagged for color coded syntax by Convert Script to Markup Code]

Hi Jon,

That is wierd and wacky.

That’s right. It’s only the variables that are either local or global. The data to which they point are the same.

In your modify_the_list_contents() handler, you’ve got round this by setting my_list to ‘my_list’s contents’. This is the same as setting it to ‘my_list’s items’. It sets my_list to another list containing exactly the same items. You can change the new list without changing the original. But if one of the items is itself a list, changing its contents will change the contents of that sublist in the original:

set my_list to {{1, 2, 3}, 2, 3}
set c_list to my_list's contents
set item 2 of c_list to "Hello"
my_list
--> {{1, 2, 3}, 2, 3}

-- But:
set item 2 of item 1 of c_list to "Hello"
my_list
--> {{1, "Hello", 3}, 2, 3}

For a completely new list with no shared data, there’s the ‘copy’ command:

set my_list to {{1, 2, 3}, 2, 3}
copy my_list to c_list

set item 2 of item 1 of c_list to "Hello"
my_list
--> {{1, 2, 3}, 2, 3}

In a handler, that could of course be:

on modify_the_list_contents(my_list)
  set copy my_list to my_list
  
  -- etc.

Hi, Jon. Sorry, I didn’t notice your explanation of the behaviour before replying above.

Going into Precise Language Mode, I differentiate between a “reference” (an AppleScript construct that describes how one item relates to another) and a “pointer” (which is how the value of a variable, or of a list item, is located in memory). What’s passed to a handler as a parameter is a copy of the pointer that points the way to the physical location of the data in memory. If it were a reference, dereferencing it with the ‘contents of’ operator would simply return the original item, and you’d still be having problems with shared data.

Hope that makes sense. I’ve got to rush out now…

Thanks for the explanation Nigel.

Jon