Pass by reference?

I have read that a “list” is passed by reference, and have seen it work in an example on page 141 of “AppleScript The Definitive Guide”, 2nd Edition. But I am missing something because the following code doesn’t work as I expect.


local pathName -- The path to the zvents monthly posting data.
set pathName to "Macintosh HD:Applications:Panorama:Monthly Postings:zvents:"

local catList -- A list that contains triples comprising an event name and the two catetories used last time that event name was used.
set catList to {}

display dialog ("Count of catList = " & (count of catList))
my buildList(catList, pathName, "zvents categories", "newline")
display dialog ("Count of catList = " & (count of catList))

on buildList(theList, thePathName, theFileName, theDelimiter)
	local fp
	
	set fp to open for access file (thePathName & theFileName)
	if (theDelimiter is "newline") then
		set theList to read fp from 1 using delimiter "
"
	end if
	if (theDelimiter is "return") then
		set theList to read fp from 1 using delimiter "
"
	end if
	
	repeat with next from 1 to (count of theList)
		display dialog item next of theList
	end repeat
	
	close access fp
	
	return
	
end buildList


When I run this, as I expected the first "display dialog (“Count of catList = " & (count of catList))” shows the count to be “0”. In the handler the repeat loop correctly displays the 12 values that should be in the list. What I don’t understand is that the "display dialog (“Count of catList = " & (count of catList))” following the call to buildList() also show the count as “0”. If I have this code right and if catList is passed by reference (as I understand that term from other languages), then the count should be 12.

I need your help understanding where I have gone awry.

Thanks,

Jerry

By passing a list into a handler, the list won’t get changed. It’s better to let the handler return a new created list:

set pathName to "Macintosh HD:Applications:Panorama:Monthly Postings:zvents:"

set catList to {}
display dialog ("Count of catList: " & (count catList))
set catList to buildList(pathName, "zvents categories", return)
display dialog ("Count of catList: " & (count catList))


on buildList(aPath, aFileName, aDelimiter)
	set fileToRead to (aPath & aFileName) as alias
	set OA to open for access fileToRead
	set newList to read OA from 1 using delimiter aDelimter
	
	close access OA
	
	return newList
end buildList

Hope it works,
ief2

PS: "
" is the same as return

Thanks for the reply. I think I can pick up a couple of pointers from your coding style. Using “a” rather than “the” as a parameter prefix will clearly save some keystrokes and I was unaware of the return and linefeed constants.

I have tried that variation and have also tried the variation where I copy the new values to the end of the list in the handler. I usually think of pass by reference as being something like having a pointer in C. In that case you can do anything to the argument in the subroutine that you can do in the level of code where it is defined. That seems to clearly not be the case in AppleScript. I am trying to understand just what the differences are.

Thanks,

Jerry

Hi, Jerry.

(I see ief2’s replied while I’ve been composing this, but there’s some more detail about passed lists below.)

At the top of your buildList() handler, the local ‘theList’ variable does indeed contain the same list as the ‘catList’ variable outside the handler. But then ‘theList’ is set to something else ” ie. the result of the ‘read’. In other words, you’re changing the contents of the variable, not the contents of the list.

‘read . using delimiter’ returns a list. If you want the items in that list to be added to the catList/theList one, you have to insert them like this:

set readList to read fp from 1 using delimiter "
"

repeat with next from 1 to (count readList)
	set end of theList to item next of readList
end repeat

catList will then contain the items when you look at it outside the handler. But I assume you’re just experimenting here. In practice, it’s better just to return the result of the read and set ‘catList’ to that:


local pathName -- The path to the zvents monthly posting data.
set pathName to "Macintosh HD:Applications:Panorama:Monthly Postings:zvents:"

local catList -- A list that contains triples comprising an event name and the two catetories used last time that event name was used.

set catList to buildList(pathName, "zvents categories", "newline")
display dialog ("Count of catList = " & (count of catList))

on buildList(theList, thePathName, theFileName, theDelimiter)
	if (theDelimiter is "newline") then
		set delim to linefeed
	else if (theDelimiter is "return") then
		set delim to return
	end if
	
	set fp to (open for access file (thePathName & theFileName))
	try
		set theList to (read fp from 1 as string using delimiter delim)
	on error msg
		close access fp
		display dialog msg
	end try
	close access fp
	
	return theList
	
end buildList


Nigel,

Thanks for the very helpful explanation. I was thinking that “theList” was just another name for “catList”. Instead, it is a separate variable that points to the same piece of memory as catList. If I operate on it with the repeat loop, then AppleScript dereferences the address and operates on the real catList. If I set “theList” to a new list, then it contains the address of the new list and and no longer has any relationship to catList. Is that about it?

Jerry

Spot on. :slight_smile: