reset for loop counter

Simple question: if I have a for loop (zsh) over an unreliable list, by which I mean the list contains entries that can't be predicted beforehand, then can I reset the for loop counter? This demonstrates what I'm asking for:

# e.g. list=(1 5 2 9)
for i in \$list ; do
[[ \$i = 2 ]] && i=\${list}
done

(This example will obviously loop forever if it worked.)

I can only think of doing it like this:

for ((j=1; j<=\${#list}; j++)); do
[[ \${list[\$j]} = 2 ]] && j=1
done

Is there a simpler way of doing it? ("Simpler" meaning easier to follow with the eye what you're doing.)

• If the list was (1 5 1 2 9), how would zsh know which 1 i=\${list} should bring you back to? – Stéphane Chazelas Jul 23 '14 at 15:33
• Other than the cosmetic replacement to (( list[j] == 2 )) && j=1 or (( list[j] == 2 && j = 1)), I don't think you'll get any much better. – Stéphane Chazelas Jul 23 '14 at 15:36
• I only need to reset to the beginning of the list, which I should have mentioned. The reset position is not dependent on the contents of list. – Zorawar Jul 23 '14 at 15:39
• No, I was fearing I would not get any better. I was hoping for some magical builtin command. – Zorawar Jul 23 '14 at 15:41

You could do something like:

alias   forever='while ((1))' \
try-again='continue 2'  \
ok-done='break'

forever {
for i ("\$list[@]") {
(( i == 2 )) && try-again
}
ok-done
}

Note that you need "\$list[@]" instead of \$list if you don't want to omit the empty elements.

Not a lot more legible than:

for ((i = 1; i <= \$#list; i++)) {
(( list[i] == 2 )) && i=1
}

though.

• No, not really, but its an interesting way of doing it that didn't occur to me. – Zorawar Jul 23 '14 at 20:02