List iteration issue

From time to time I run into this strange issue:

For example, I iterate through a list like this:

repeat with anItem in aList
<do something with anItem>
end repeat

Suddenly, after working with no problems, this script starts giving an error:

[format]Can’t do whatever with (item 1 of {“item1”, “item2”, …})[/format]

I have to replace it with iterating through item numbers, which works:

repeat with n from 1 to (count aList)
set anItem to item n of aList
<do something with anItem>
end repeat

Actually, in most cases it’s users who report this issue - while I can rarely reproduce it.

Is it a known issue with the “repeat” function?

Should I just avoid the iteration by item altogether and always iterate through numbers?

Thanks,
Leo

Hi. Look at what’s actually being returned in the editor. anItem in a list would be a positional reference. You want anitem’s item 1 or anitem’s contents to be the actual item.

Hi.
Mark Anthony implies the following below. Invalid script:


set aList to {{"a"}, {1}}

repeat with anItem in aList
	return anItem
end repeat

Correct script:


set aList to {{"a"}, {1}}

repeat with anItem in aList
	return item 1 of anItem -- OR:
	-- return contents of anItem
end repeat

It is better to use an unindexed reference to the item, where it is possible, because it is more efficient. So, no need to avoid this form.

As Marc Anthony already mentioned anItem is a positional reference.

In most cases AppleScript dereferences the items implicitly.

However if you are going to compare a string or modify the item in the list you have to dereference the item explicitly with contents of

set aList to {"alpha", "beta"}

repeat with anItem in aList
	if contents of anItem is "beta" then
		set contents of anItem to "gamma"
		display dialog anItem buttons {"OK"} default button 1 --> "gamma"
	end if
end repeat

The other suggestion item 1 works only with nested lists. In my example it’s pointless.

The likely reason for the issue noted by the OP has been identified, but, FWIW, I thought I would post a few examples to further illustrate:

set theList to {"OK"}

repeat with anItem in theList
	anItem --> item 1 of {"OK"}
	anItem = "OK" --> false
	contents of anItem --> "OK"
	contents of anItem = "OK" --> true
	anItem as text --> "OK"
	anItem as text = "OK" --> true
end repeat

The following is an example from the AppleScript Language Guide of implicit coercion, which Stefan makes note of:

set total to 0
repeat with aNumber in {1, 2, 3, 4}
	set total to total + aNumber -- aNumber is coerced from object specifier to integer
end repeat -- result is 10

A question raised by the OP is:

IMO the answer is no. Both methods work fine and have their use.

Thanks for all the replies.

After further investigation, I found out that there’s no problem indeed with the “repeat with … in …” iteration method. The problem was actually with the value of list item itself, which gave the error.

What confused me was the wording of the error:

[format]Can’t do whatever with (item 1 of {“item1”, “item2”, …})[/format]

I had to coerce the item into string (or use “contents of”, as suggested in some replies) to get a coherent error:

[format]Can’t do whatever with “item1”[/format]