Script Debugger 7 bug with list as reference

I’m having a problems with Script Debugger 7.0.12
When I pass a list to a subroutine, it is passed as reference according to AppleScript Language Guide.
My subroutine adds items to the end of the list, but when it returns, the list shown on the right in the variable viewer pane shows the list as empty (unchanged), yet when i then issue a get list command, the proper result shows in the Results Pane

example code


on run
	local alist
	set alist to {}
	testList(alist, 32) -- this list in the Variable Viewer Pane will show as empty after this command
	get alist -- this command will show the proper result
end run

on testList(blist, x)
	repeat with i from 1 to x
		set end of blist to i
	end repeat
end testList

As far as I know, it’s not a bug.
We must define the locales which we want to trace in handlers.
If I trigger the button [Step into the handler called in the next statement] I may see the behavior of the list.

on run
	local alist
	set alist to {}
	set alist to my testList(alist, 32) -- this list in the Variable Viewer Pane will show as empty after this command
	--get alist -- this command will show the proper result
end run

on testList(blist, x)
	local blist, i
	repeat with i from 1 to x
		set end of blist to i
	end repeat
	return blist
end testList

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 18 mai 2020 21:38:34

I did not know you could declare a parameter as local.
– I thought that would cause a conflict.-- edit

This does not solves my issue tho.
I was a trying to not use the set command on a list that should already be modified just by calling the subroutine. The main reason I want to do this is an some cases where i use very, very large lists

the list “alist” was already set as a local in the run handler, and that is where i want to trace it

Thanks.

Robert

That’s because you’ve declared it local. Remove the local statement.

It works!
But why does declaring it local change anything?
Isn’t it by default a local variable anyway?

Robert

No, variables declared at the top level or in an explicit run handler are global unless declared otherwise.

on run
	set aList to {"a"}
	testList()
end run

on testList()
	global aList
	display dialog (item 1 of aList)
end testList

AppleScript scope is complicated.

But then if are global why this triggers an error?

on run
	set aList to {"a"}
	set bList to {} -- This also should be "global"
	testList()
	display dialog (item 1 of bList) -- ERROR HERE
end run

on testList()
	global aList
	set bList to {"c"} -- fails to update the "global" variable bList ...
	display dialog (item 1 of aList)
end testList

Or … have I misunderstood the concept of “global”?

I agree !!!

Sort of. As I said, scope is complex in AppleScript. The best explanation of it is still in Matt Neuberg’s book.

I got a reply from Mark Alldritt at LateNight Software
Here’s what he said:

Yes, this is a limitation of the technique we use to implement step-wise execution. Modifying variables in the way you are doing it is not noticed automatically by Script Debugger. You can force Script Debugger to see the change to the alist variable using this specially formatted comment:

--=alist

This tells Script Debugger to sample the value of the variable(s) listed at that point in the code.

Cheers
-Mark

– YES it works

Robert

robertfern,

this is not specifically Script Debugger issue. When I run your original script in the Script Editor, I get the same unwanted result. This means: you should pass not whole alist object, but only its contents:


on run
	set alist to {}
	my testList(contents of alist, 32) -- this list in the Variable Viewer Pane will show as empty after this command
	return alist -- this command will show the proper result
end run

on testList(blist, x)
	repeat with i from 1 to x
		set end of blist to i
	end repeat
end testList

Works as normal in my “Script Editor”
and since my issue is with a debugging feature, not sure how that applies to “Script Editor”.

Also, in this instance of a project i’m working on, I would never pass contents of list as my list is potentially “extremely” large and passing as reference is best to cut down on multiple copies in memory and the creating, copying, and destroying these large lists in memory. As this would cause performance issues.

Please elaborate on what is not working for you,

Thanks,

Robert

Seeing your original script again. As you tried alist as local variable, I guess that you wanted only the list blist (local) to be modified, and the list alist (global) to remain empty. So… its correct result should be empty list alist, and not contents of blist. Your original script doesn’t do the correct job for you either. The only difference between us is that you don’t understand this.

Even if my guess does not hit the target, and you still want to change the contents of the 1st list (global variable) having the 2nd list as independent list (that is, as a local variable of handler testList), then the correct script should be following:


on run
	set alist to {}
	set alist to my testList(contents of alist, 32)
end run

on testList(blist, x)
	repeat with i from 1 to x
		set end of blist to i
	end repeat
	return blist
end testList

You totally misunderstood.

The correct list should be {1,2,3,4…,31,32} as it is.

blist in the subroutine is “a reference to” alist as this is how AppleScript passes lists as parameters, which is what I want.
So modifying blist in the subroutine is actually modifying alist in the main routine, also what I wanted.

So it is acting as it should

Robert

If you didn’t need to worry about changing the contents of alist, and you wanted to do just that, then it is incredibly difficult to understand why you tried to make it a local variable.

My entire issue had nothing to do with the list being local or not, but was solely on an issue with “Script Debugger”'s ability to debug the changes.

Robert