I have noticed several times that using a repeat with i in l form of loop will sometimes prevent the value of i from working as I expect. A simplified example with the resulting event log follows.
set l to {missing value, "a", "B", missing value, 3}
log "--- list repeat"
repeat with i in l
if i is not missing value then log i
if i is "a" then log "^^^ \"a\""
end repeat
log "--- indexed repeat"
repeat with _i from 1 to count of l
set i to item _i of l
if i is not missing value then log i
if i is "a" then log "^^^ \"a\""
end repeat
-- Event Log output follows
(*--- list repeat*)
(*missing value*)
(*a*)
(*B*)
(*missing value*)
(*3*)
(*--- indexed repeat*)
(*a*)
(*^^^ "a"*)
(*B*)
(*3*)
Why is it that, when using the list-based repeat loop, the value of loop variable i can not be correctly compared to missing value or “a”?
I feel like I am missing something fundamental here, since this seems like it should be straightforward.
Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 419.3
Operating System: Mac OS X (10.4)
the index variable in the form repeat with i in l is not the value of the list elememt,
it’s a reference to the list element. AppleScript often dereferences the value(s) automatically,
but in this case you need contents of to get the value
set l to {missing value, "a", "B", missing value, 3}
log "--- list repeat"
repeat with i in l
if contents of i is not missing value then log i
if contents of i is "a" then log "^^^ \"a\""
end repeat
log "--- indexed repeat"
repeat with _i from 1 to count of l
set i to item _i of l
if i is not missing value then log i
if i is "a" then log "^^^ \"a\""
end repeat
OK, that makes sense. I even tried to check for something like that by getting the class of i, but the results turned out to be the same in both loops. I thought I might see something like reference for the repeat with i in l loop instead of integer or string. Since the results were the same, I discounted the possibility of a wrapper. Apparently AppleScript was doing its automatic dereferencing when I asked for the class, but not when doing the equality comparison.
Now that I know to look for a reference, I see it in the AppleScript Language Guide, but it isn’t as prominent as I would expect. I actually had to use Find… to catch all the mentions of reference in the description of the list form of the loop.
And the operations that always require dereferencing (contents of) are the boolean operations, i.e., if you use your repeat variable in an if statement, you must dereference it because myVar is never equal to item n of {some list} taken as a whole.
More precisely, it’s equality tests where dereferencing (or coercion) is required. Greater than, less than, contains, is in, and properties and elements of the referenced item don’t require it explicitly.
I see your point for “equals/is not equal to”, but while following my pedantry, I found that not all boolean operations require the dereferencing:
Edit: I that Nigel Garvey’s post while I was composing this one also points out that the equality tests are special.
set l to {1, "1", 3, "3"}
repeat with i in l
log "---"
if i is equal to 1 then log "i = 1"
if contents of i is equal to 1 then log "contents of i = 1"
if i is equal to "3" then log "i = \"3\""
if contents of i is equal to "3" then log "contents of i = \"3\""
if i is less than 2 then
log "i < 2"
else
log "i not < 2"
end if
if i is greater than or equal to "3" then
log "i >= \"3\""
else
log "i not >= \"3\""
end if
log i & "X"
log i + 10 -- always coerced to number
end repeat
-- Event Log:
(*---*)
(*contents of i = 1*)
(*i < 2*)
(*i not >= "3"*)
(*1, X*)
(*11*)
(*---*)
(*i < 2*)
(*i not >= "3"*)
(*1X*)
(*11*)
(*---*)
(*i not < 2*)
(*i >= "3"*)
(*3, X*)
(*13*)
(*---*)
(*contents of i = "3"*)
(*i not < 2*)
(*i >= "3"*)
(*3X*)
(*13*)
The dereferencing is happening automatically for <, >=, + and &, but not for is equal to.
It seems to me that the automatic dereferencing is probably part of the automatic coercion done for operators and commands. I found a hint at this in the coercion section of the AppleScript Language Guide:
and
The equality operations seems to be fairly special in that they do not do any coercion. From the “Equal, Is Not Equal To” section: