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.
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
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.
(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
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?