I want to, for example, repeat a loop 5 times. But inside of the loop I check a condition. If that condition is true I want to skip a cycle of the loop. Here’s my example…
set L to {}
repeat with i from 1 to 5
if i is 2 then set i to i + 1
set end of L to i
end repeat
L
result → {1, 3, 3, 4, 5}
shouldn’t it be → {1, 3, 4, 5}
You can see that my condition is if i=2. In this case I increment i by 1 thinking that this will skip a cycle in the repeat loop since the loop is counting by i… but it doesn’t. The repeat loop repeats 5 times not matter what.
Am I crazy thinking this should work? Does anyone know how to skip a repeat loop cycle?
I see you just added this…
But why can’t I? It doesn’t make sense to me. The loop is counting by i isn’t it? It’s obvious now that it isn’t counting by i, I just thought it was.
There’s no way to skip a cycle once the loop starts?
I believe you StefanK, but it just surprises me. I still don’t understand why I can’t change the index variable… other than the fact that applescript doesn’t allow this.
I believe it’s effectively the same thing as this:
repeat with i in {1, 2, 3, 4, 5}
i
end repeat
In this use, i is actually a reference instead of a number, but the behavior is the same. I don’t think AppleScript has a built-in command with the behavior you’re looking (In other langauges, you might use a for/while/etc. loop).
Aside from the previous paragraph, I think incrementing i in another language (see the previously mentioned loops) would cause a (similar) set end of L statement to execute, as the variable is only evaluated at the beginning of the loop.
What you would likely use is whatever continue/break/next/etc. statement that language has.
Unfortunately, AppleScript doesn’t have a statement like the ones I just mentioned. However, you might be able to achieve that behavior by other means; Try something like this:
set test to {}
repeat with i from 1 to 5
try
-- conditions where you want to skip the repeat
if i is 2 then error "next repeat"
-- whatever else
set end of test to i
on error errMsg number errNum
-- pass on any error messages that occured here
if errMsg is not "next repeat" then error errMsg number errNum
end try
end repeat
test
--> {1, 3, 4, 5}
That does work John M, but I have a really long script and it seemed silly to stick the whole script inside of an if/then statement… but I guess that’s what I have to do.
There’s no reason I can see not to put large chunks of script in an ‘if’ block. A thing I have found handy is to comment near the ‘end if’ to note which ‘if’ you are referring to.
Thanks Bruce. I see now that I have to use a try/on error statement or a second repeat loop or an if/then statement. It all amounts to the same thing as StefanK said, you can’t increment an index variable in applescript. Now I know! :rolleyes:
It just seemed easier to increment the counter variable. And then I wrote my script that way and I was getting errors and it took me a long time to figure out the problem. It really frustrated me when I figured out my problem!
I assumed this was case. (Personally, I don’t having another level of indentation for something like this.) Just to clarify, there’s nothing syntactically wrong with using an if statement like John did.
First, a correction; AppleScript’s until and while statements worked as expected:
set test to {}
set i to 1
repeat until i > 5
-- conditions where you want to skip the repeat
if i is 2 then set i to i + 1
-- whatever else
set end of test to i
-- manually increase the variable
set i to i + 1
end repeat
test
--> {1, 3, 4, 5}
What I meant to point out is that the otherrepeat statements in AppleScript lack a continue/break/next/etc. statement.
Also, I meant to express that AppleScript’s repeat with aVariable statement is more of an iterator; That is, it iterates over multiple values (instead of controlling the value yourself; This is basically the same point that StefanK made).
That’s the repeat loop I was looking for Bruce… one where I control the counter variable. I should have thought of that myself! Unfortunately for me I’ve spent the last hour or so re-organizing my script to accomodate an if/then statement like we’ve been talking about. So now I’d have to go back and change things again to utilize the “repeat until” loop! :o
The solutions proposed in this thread are still the only way to achieve this? I have an infinite loop that I sometimes want to restart depending on a condition. That is, there is no index to manipulate.
I don’t know of a solution not included in this thread, but Stefan’s suggestion can be used with an infinite loop. Two examples,
--EXAMPLE ONE
try
set theCounter to 0
repeat
repeat 1 times
set theCounter to theCounter + 1
if theCounter is 3 then exit repeat --skip counter 3
display dialog "The counter is " & theCounter
if theCounter is 5 then error --exit repeat loops
end repeat
end repeat
end try
display dialog "The repeat loops have been exited. The last counter was " & theCounter & "."
--EXAMPLE TWO
set theCounter to 0
set exitRepeat to false
repeat
if exitRepeat is true then exit repeat
repeat 1 times
set theCounter to theCounter + 1
if theCounter is 3 then exit repeat --skip counter 3
display dialog "The counter is " & theCounter
if theCounter is 5 then set exitRepeat to true --exit repeat loops
end repeat
end repeat
display dialog "The repeat loops have been exited. The last counter was " & theCounter & "."
Infinite repeats aren’t a good idea, as you’ve probably read elsewhere. But otherwise, as others have shown above, there are other kinds of repeat besides indexed repeats, eg.:
repeat until (some condition met) -- pseudocode
end repeat
If by “restart” you mean “go back to the repeat’s initial conditions”, you might do something like this:
-- Set up the initial conditions here.
repeat
if (some condition met) then -- pseudocode again
-- Reset to the initial conditions here.
end if
-- Do whatever this repeat does.
end repeat