7

Say I have a nested loop, is there a way to break out of the outer loop from the inner one? For example this code:

for i in range(3)
    for j in range(5)
        echo i j
        if i == 1 && j == 2
            break
        endif
    endfor
endfor

only breaks out of the inner loop, but how could I get out of the outer one? is there a goto command?

Jake
  • 213
  • 1
  • 5

1 Answers1

5

There is no goto in vimscript [1]. Like most languages that lack goto, you'll need to handle this using a variable:

let breaking = 0
for i in range(3)
    for j in range(5)
        echo i j
        if i == 1 && j == 2
            breaking = 1
            break
        endif
    endfor
    if breaking
       break
    endif
endfor

You can also use j outside of the loop, although this is a bit brittle to any code changes later.

for i in range(3)
    for j in range(5)
        echo i j
        if i == 1 && j == 2
            break
        endif
    endfor
    if i == 1 && j == 2
       break
    endif
endfor

Another way to handle this is with a double loop

let Zip = {a,b -> a->mapnew({_,x -> b->mapnew({_,y -> [x, y]})})->flatten(1)}

for [i, j] in Zip(range(3), range(5)) echo i j if i == 1 && j == 2 break endif endfor

Zip is quite cryptic, but just demonstrating the double for concept.

Finally, you can restructure your program to avoid the nested loop,

function! DoWork(i)
    for j in range(5)
        echo a:i j
        if a:i == 1 && j == 2
            return 1
        endif
    endfor
    return 0
endfunction

for i in range(3) if DoWork(i) break endif
endfor

or in vim9script,

vim9script

for i in range(3) if () => { for j in range(5) echo i j if i == 1 && j == 1 return 1 endif endfor return 0 }() break endif endfor

[1] of course, there is a goto in vim script but it definitely doesn't do what you want!

Mass
  • 14,080
  • 1
  • 22
  • 47