how to skip a cycle in a repeat loop?

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?

Hi regulus,

a workaround is a second repeat loop

set L to {}
repeat with i from 1 to 5
	repeat 1 times
		if i is 2 then exit repeat
		set end of L to i
	end repeat
end repeat
L

You can’t modify an index variable in a repeat loop

1 Like

Thanks StefanK, but I was hoping not to “work around” it. I don’t understand why what I wanted to do doesn’t work.

Here’s another work-around too by the way…

set L to {}
repeat with i from 1 to 5
	if i is not 2 then set end of L to i
end repeat
L

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?

As I mentioned before, setting an index variable in a repeat loop has no effect

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.

Hi,

Perhaps I’m missing something, but why not use ‘if’ this way:

set L to {}
repeat with i from 1 to 5
	if i is not 2 then
		set end of L to i
	end if
end repeat
L

Best wishes

John M

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.

Hi Regulus,

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.

John M

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.

I had too many thoughts in my head at once…

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 other repeat 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

Today has been a hard day! :smiley:

According to the AppleScript Language Guide:

A similar situation applies with ‘repeat with . in .’ repeats.

If you don’t like a lot of indented code within an ‘if’ block, you could separate it off into a handler and just have the call in the block.

Good one Nigel, thanks. That explains how it works and why changing the value of the variable doesn’t work.

Hi,

Also, you could place your long script as a script object, then run the script object when needed.

gl,

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 & "."

Hi.

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