Can't make x into type reference

I made a list-creation handler in a library that used globals for a list (gList) and a reference to gList (gListRef). I wanted to shave 2.5 seconds from the initial load time. The handler worked fine in Script Debugger (SD) and Script Editor (SE). When I called the handler from the main script, I got the error “Can’t make gList into type reference.” The first time I attempted to “copy n to the end of gListRef”

I converted the global gList into a local variable and then the handler produced the error when called from the same script.

Then I tried to look up the AppleScript Language Guide and found nothing. So I just made a script using their examples and found that the routine did not error when embedded in the run handler but errored when called. Same results after restart. MacOS 10.11.06, Same results in SD and SE. What gives?

AppleScript Language Guide

 on run
	if false then
		set bigList to {}
		set bigListRef to a reference to bigList
		set numItems to 100000
		set t to (time of (current date)) --Start timing operations
		repeat with n from 1 to numItems
			copy n to the end of bigListRef
		end repeat
		set total to (time of (current date)) - t --End timing
	else
		makeBigList()
	end if
end run

on makeBigList()
	set bigList to {}
	set bigListRef to a reference to bigList
	set numItems to 100000
	set t to (time of (current date)) --Start timing operations
	repeat with n from 1 to numItems
		copy n to the end of bigListRef
	end repeat
	set total to (time of (current date)) - t --End timing
end makeBigList

Hi.

The bigList in the handler is a local variable, and you can only make references to globals, properties, run-handler variables, or application objects. An alternative to actually using a global or a property to is define a script object in the handler with its own list property:

on makeBigList()
	script o
		property bigList : {}
	end script
	
	set numItems to 100000
	set t to (time of (current date)) --Start timing operations
	repeat with n from 1 to numItems
		set end of o's bigList to n
	end repeat
	set total to (time of (current date)) - t --End timing
end makeBigList

The expression o's bigList is equivalent to the value of bigListRef, except that it’s compiled directly into the code and refers to the script object o instead of to the main script. The variable o is a local, so you’d need to return the list if you wanted to use it outside the handler, but the property allows the form of reference to the list variable which gives the speed advantage.

1 Like

This is super helpful. I could not find that information in the Language Guide but inferred much of it. Your solutions seems like it is what I need.

Hi,

Unless I’m missing something, it’s the “copy n to the end of aList” that slowed down your script.

As in Nigel’s example, all you need is “set end of aList to n”.

Nigel offered an interesting approach to include a script inside a handler (of which I wasn’t even aware before). I sure will use it in the future to specify properties inside a handler!

But I also tried a more traditional one - and didn’t notice any speed difference:

on makeBigList()
set bigList to {}
	
	set numItems to 100000
	set t to (time of (current date)) --Start timing operations
	repeat with n from 1 to numItems
		set end of bigList to n
	end repeat
	set total to (time of (current date)) - t --End timing
	return bigList -- if needed at all
end makeBigList

Once again, it’s “copy to the end” that slowed down things as far as I understand.

Hmm! It seems to be largely as you describe now. Using a more precise timing method, I’m getting results along these lines:

‘set’ without script object: 1.16 seconds
‘set’ with script object: 1.07 seconds
‘copy’ without script object: 117.558 seconds
‘copy’ with script object: 1.126 seconds

It’s the first result that’s surprising if you’ve been scripting a long time.

1 Like

Interesting…

My timing method was more crude indeed. In any case, it looks like using the script object always gives some speed advantage (even if a few milliseconds in this case).

Yes. And here I thought it was my coding that was getting more efficient!