exit a single repeat

I find that this script beeps with five second intervals and then stops. I want it to beep 10 times with five second intervals and then start to beep very quickly.

set counter to 0
repeat
	beep
	repeat
		beep
		delay 5
		set counter to counter + 1
		if counter is 10 then
			exit repeat
		end if
	end repeat
end repeat

For me, having the following is no solution

set counter to 0
repeat
	beep
	delay 5
	set counter to counter + 1
	if counter is 10 then
		exit repeat
	end if
end repeat
repeat 10 times (*Don't need to force quit*)
	beep
end repeat

:frowning: How can I exit one repeat but not the other?

Would this not work? Edit: Sounds like it wouldn’t; May be we can make it work though.

repeat 10 times
	beep
	delay 5
end repeat

beep 10

Edit:

Um, you sort of have it right; exit repeat in the second loop is doing what it’s supposed to do. However, the first loop goes back around and starts the second loop, and it will go on forever because counter will never be 10 again.

Maybe you want to reset the counter each time:

repeat
	set counter to 0
	display dialog "Primary loop"
	repeat
		display dialog "Secondary loop"

		set counter to counter + 1
		if counter is 3 then exit repeat
	end repeat
end repeat

If you have a set number of times that you want it to beep, then I’d assume that you have no reason to put one repeat inside of another and try to exit just the inner one.

For how long? Since applescript can only be written linearly, there’s no way for you to be “doing something” while waiting for the repeat to end, so you have to determine how you’re going to establish when to quit repeating.

Assuming that you want to beep X times, then you could hard code it like this…

repeat 10 times
	delay 5
	beep
end repeat
repeat 10 times
	delay 0.5
	beep
end repeat

… or you could get a bit more creative and write some more portable code like this…

repeatWithDelay(10, 5)
repeatWithDelay(10, 0.5)

to repeatWithDelay(_repeat, _delay)
	repeat _repeat times
		beep
		delay _delay
	end repeat
end repeatWithDelay

j

Actually, I was hoping for an exit to a single repeat, not both but they would be still nested: here’s what I actually have.


tell application "iTunes"
			repeat
				play
				set trackname to the name of the current track
				set but1 to the button returned of (display dialog "Song:" & trackname & return & "Playing" buttons {"<<", "][", ">>"} with icon 1 with title "iTunes: Play")
				if but1 is "<<" then
					rewind
				else if but1 is ">>" then
					fast forward
				else
					pause
					set but1 to the button returned of (display dialog "Song:" & trackname & return & "Paused" buttons {"quit", ">", "search"} with icon 1 with title "iTunes: Play")
					if but1 is "quit" then
						quit
						tell application me
							quit
						end tell
					else if but1 is ">" then
						play
						exit repeat
					else
						play
						repeat
							set txtr to the button returned of (display dialog "Search" buttons {"<", "Ok", ">"} with icon 1 with title "Search for song")
							if txtr is "<" then
								previous track
							else if txtr is ">" then
								next track
							else
								exit repeat
							end if
						end repeat
					end if
				end if
			end repeat
		end tell

I suppose I should have posted this the first time round, sorry.

I don’t see what the problem is. Are you talking about playing the song after pausing it?

Yes, when I pause the song, everythings is fine. Press the play button and it will exit all repeat loops causing it to quit.

Um, that is only inside one repeat loop.

I never really acknoledged all thoes people calling me an IDIOT #@%$&*!§± ! But now, I accept the compliments.
SORRY GUYS!

Looking for a global exit from inner loop. Is there a simpler solution?

Beginner question. Thank you in advance for a tip how to eliminate code duplication.

set counter to 0
repeat 10 times
say "outer " & counter
repeat
say "inner " & counter
set counter to counter + 1
if counter is 4 then
say "exit inner repeat on counter = " & counter
exit repeat
end if
end repeat
if counter is 4 then
say "exit outer repeat on counter = " & counter
exit repeat
end if
end repeat

Hi.

It’s usually best to try to rethink the structure so that you don’t actually need to exit it from an inner repeat. In your example, the outer repeat exits on its first iteration, so it may as well not be a repeat. The simplest answer to the OP’s query (as originally posed) would have been to replace the inner repeat with an ‘if’ condition:

set counter to 0
repeat
	beep
	set counter to counter + 1
	if (counter ≤ 10) then delay 5
end repeat

If you do need to exit an entire nested repeat structure from an inner repeat, one idea would be to put it in its own handler, from which you could simply ‘return’ when the inner condition was met:

on doNestedRepeats()
	-- Blah blah blah
	repeat
		-- Blah blah blah
		repeat
			-- Blah blah blah
			repeat
				-- Blah blah blah
				if (conditionIsMet) then return
			end repeat
		end repeat
	end repeat
end doNestedRepeats

doNestedRepeats()

Adding a return code would also enable the calling program to identify the specific repeat loop that was exited:

on doNestedRepeats()
	-- Blah blah blah
	repeat
		-- Blah blah blah
		if (outermostRepeatLoopConditionIsMet) then return 101
		repeat
			-- Blah blah blah
			if (middleRepeatLoopConditionIsMet) then return 102
			repeat
				-- Blah blah blah
				if (innermostRepeatLoopConditionIsMet) then return 103
			end repeat
		end repeat
	end repeat
	return 100
end doNestedRepeats

doNestedRepeats() returning returnCode
if returnCode = 101 then
	-- The outermost repeat loop condition was met
else if returnCode = 102 then
	-- The middle repeat loop condition was met
else if returnCode = 103 then
	-- The innermost repeat loop condition was met
end if

An alternative approach to achieve this functionality is to enclose the nested repeat loops in a try block. A user-thrown error allows early exit from any of the nested repeat loops. Numbering the user-thrown error allows ready identification of the specific repeat loop that was exited. The user-thrown error numbers should be positive integers in order not to conflict with Applescript’s negative error numbers:

try
	repeat
		-- Blah blah blah
		if (outermostRepeatLoopConditionIsMet) then error number 101
		repeat
			-- Blah blah blah
			if (middleRepeatLoopConditionIsMet) then error number 102
			repeat
				-- Blah blah blah
				if (innermostRepeatLoopConditionIsMet) then error number 103
			end repeat
		end repeat
	end repeat
on error m number n
	if n = 101 then
		-- The outermost repeat loop condition was met
	else if n = 102 then
		-- The middle repeat loop condition was met
	else if n = 103 then
		-- The innermost repeat loop condition was met
	else
		-- Rethrow any unplanned error
		error m number n
	end if
end try

That is the first thing someone should look at!

I want to add that I also see posts come by where the wrong repeat loop is used. Sometimes you you need more than 1 condition or in this case one condition needs to be used in different loops. Using a different loop like repeat until and repeat while could eliminate these problems as well. That is because repeat with and repeat n times are designed to do an known amount of times while other loops are not.

There is no global exit, so to give an short answer: Not possible. When you need a programming language something to do that it’s not designed to do, your design is by definition not flawless.

The example code makes no sense in terms of how it should work. As far as I’m concerned, in terms of efficiency, the result would be the same with an single repeat with counter from 1 to 4 loop. So could you be more specific on what you exactly want so we can provide you the best possible answer? Based on your example code I would go for an additional boolean value than you can set in the inner loop and check in the other loop.

set done to false
set counter to 0
repeat 10 times
	say "outer " & counter
	repeat
		say "inner " & counter
		set counter to counter + 1
		if counter is 4 then
			say "exit inner repeat on counter = " & counter
			set done to true
			exit repeat
		end if
	end repeat
	if done then exit repeat
end repeat

Since it seems that you’re doing nothing with the 10 loops I would change the outer loop to repeat until done so you can eliminate the last line in the main loop.