43

I have a simple 'repeat with' in an AppleScript, and would like to move on to the next item in the "repeat" conditionally. Basically I'm looking for something similar to "continue" (or break?) in other languages.

I'm not well versed in AppleScript but I have found it useful a few times now.

danieljimenez
  • 1,390
  • 4
  • 17
  • 26

7 Answers7

60

After searching for this exact problem, I found this book extract online. It exactly answers the question of how to skip the current iteration and jump straight to the next iteration of a repeat loop.

Applescript has exit repeat, which will completely end a loop, skipping all remaining iterations. This can be useful in an infinite loop, but isn't what we want in this case.

Apparently a continue-like feature does not exist in AppleScript, but here is a trick to simulate it:

set aList to {"1", "2", "3", "4", "5"}

repeat with anItem in aList -- # actual loop
    repeat 1 times -- # fake loop
        set value to item 1 of anItem

        if value = "3" then exit repeat -- # simulated `continue`
        
        display dialog value
    end repeat
end repeat

This will display the dialogs for 1, 2, 4 and 5.

Here, you've created two loops: the outer loop is your actual loop, the inner loop is a loop that repeats only once. The exit repeat will exit the inner loop, continuing with the outer loop: exactly what we want!

Obviously, if you use this, you will lose the ability to do a normal exit repeat.

ccpizza
  • 28,968
  • 18
  • 162
  • 169
Tom Lokhorst
  • 13,658
  • 5
  • 55
  • 71
  • 1
    The code above won't compile because comments in applescript are -- not # – alexyorke Dec 07 '09 at 00:13
  • 2
    In applescript 2.0 the # sign is also allowed for comments: https://developer.apple.com/library/mac/documentation/applescript/conceptual/applescriptlangguide/conceptual/ASLR_lexical_conventions.html#//apple_ref/doc/uid/TP40000983-CH214-SW8 – Joakim Sep 20 '12 at 11:58
  • 1
    The code would compile anyway because “--” precedes all the “#” and the “--” has always marked a comment in AppleScript. – Simon White Jan 24 '16 at 17:27
  • what if aList is {"1", "2", "", "4", "5"}? How can I effectively skip a null/empty string in a case like this? This code currently errors in this case with `Can’t get item 1 of "".` – Max Well Aug 01 '23 at 21:35
8
set aList to {"1", "2", "3", "4", "5"}

repeat with anItem in aList -- # actual loop
    try
        set value to item 1 of anItem

        if value = "3" then error 0 -- # simulated `continue`

        log value
    end try
end repeat

This will still give you the "exit repeat" possibillity

Skeeve
  • 89
  • 1
  • 1
7
set aList to {"1", "2", "3", "4", "5"}

repeat with anItem in aList -- # actual loop
    try -- # needed to simulate continue
        set value to item 1 of anItem
        if value = "3" then continueRepeat -- # simulated `continue` throws an error to exit the try block

        log value
    on error e
        if e does not contain "continueRepeat" then error e -- # Keeps error throwing intact
    end try
end repeat

Based on the try block based approach above but reads slightly better. Of course, since continueRepeat is not defined an error will be thrown which causes the rest of the try block to be skipped.

To keep error throwing intact include the on error clause that throws any unexpected error.

Daniel Schlaug
  • 1,504
  • 1
  • 13
  • 17
3

-- Or you could use different strategy: use the loop to loop, and do the conditional logic in a handler, like so:

set aList to {"1", "2", "3", "4", "5"}

repeat with anItem in aList
   doConditionalWork(anItem as string)
end repeat

on doConditionalWork(value)

   if value = "3" then return

   display dialog value

end doConditionalWork
Ron Reuter
  • 1,287
  • 1
  • 8
  • 14
2

Y'all are all overcomplicating it. Try this:

set aList to {"1", "2", "3", "4", "5"}

repeat with anItem in aList
    set value to item 1 of anItem
    if value is not "3" then log value
end repeat
Eurobubba
  • 37
  • 1
1

You can also use “repeat while” for loops that only repeat conditionally.

Simon White
  • 686
  • 5
  • 9
0

Based on the answer of Tom Lokhorst, here is a variant to do either break or continue, based on a isExit variable you set. For that at the end of the outer (non-fake) loop, you add

if isExit then
    exit repeat
end if

That way if isExit is true, you simply exit the outer loop too, being an effective break.

Original question/answer:

For the original question problem this would look like that, below will be a generalized one.

set aList to {"1", "2", "3", "4", "5"}

repeat with anItem in aList -- actual loop
    set isExit to false
    repeat 1 times -- fake loop
        -- do your stuff
        set value to item 1 of anItem

        if value = "3" then 
            -- simulated `continue`
            set isExit to false
            exit repeat
        end if

        if value = "69" then 
        -- simulated `break`
            set isExit to true
            exit repeat
        end if
        
        display dialog value
    end repeat

    if isExit then
        exit repeat
    end if
end repeat

Generalized

So to break this down, into an more easy example:

Say you'd want to have either continue or break in those two ifs. You can place all your code between those, I only included the code relevant for the different exit strategies.

If you want to write something like this:

repeat <condition_repeat>
    if <condition_continue> then
        continue
    end if
    if <condition_break> then
        break
    end if
end repeat

That could be written as

repeat <condition_repeat>
    set isExit to false                -- added 
    repeat 1 times                     -- added 
        if <condition_continue> then
            set isExit to false        -- changed
            exit repeat                -- changed
        end if
        if <condition_break> then
            set isExit to true         -- changed
            exit repeat                -- changed
        end if
    end repeat                         -- added
    if isExit then                     -- added
        exit repeat                    -- added
    end if                             -- added
end repeat
luckydonald
  • 5,976
  • 4
  • 38
  • 58