loop
loop runs a block over and over until something stops it: a break, a return from the enclosing custom command, or an error. It takes no condition; use while when the loop should stop as soon as a condition becomes false.
See also: loop command help and Control Flow - loop in the Book.
mut n = 1
loop {
print $n
if $n >= 3 { break }
$n += 1
}
# => 1
# => 2
# => 3Language Notes
loopis a statement. It always evaluates tonothing, and the value of the last expression in the body is discarded on every iteration. Useprintto show something, or collect results in a mutable variable.mut n = 0 loop { $n += 1; if $n > 2 { break }; $"value ($n)" } | describe # => nothingmut fib = [0 1] loop { let next = ($fib | last 2 | math sum) if $next > 50 { break } $fib ++= [$next] } $fib # => ╭───┬────╮ # => │ 0 │ 0 │ # => │ 1 │ 1 │ # => │ 2 │ 1 │ # => │ 3 │ 2 │ # => │ 4 │ 3 │ # => │ 5 │ 5 │ # => │ 6 │ 8 │ # => │ 7 │ 13 │ # => │ 8 │ 21 │ # => │ 9 │ 34 │ # => ╰───┴────╯The body is a block, not a closure. That is why it can update
mutvariables declared outside of it. A closure passed to a command likeeachcannot (see Variable Scope).Variables declared with
letinside the body are local to a single iteration and are not visible after the loop.loopdoes not accept pipeline input:1 | loop { break } # => Error: nu::parser::input_type_mismatch # => # => × Command does not support int input. # => ╭─[repl_entry #1:1:5] # => 1 │ 1 | loop { break } # => · ──┬─ # => · ╰── command doesn't support int input # => ╰────Inside a custom command,
returnleaves both the loop and the command, and it can carry a value out:def find-free-name [base: string, taken: list<string>] { mut i = 1 loop { let candidate = $"($base)-($i)" if $candidate not-in $taken { return $candidate } $i += 1 } } find-free-name report [report-1 report-2] # => report-3continueskips the rest of the current iteration and starts the next one.When the goal is to produce a list, a filter is usually simpler than a loop and a mutable variable.
generatebuilds the same Fibonacci list as above:generate {|fib| if $fib.0 <= 50 { {out: $fib.0, next: [$fib.1, ($fib.0 + $fib.1)]} } } [0 1] # => ╭───┬────╮ # => │ 0 │ 0 │ # => │ 1 │ 1 │ # => │ 2 │ 1 │ # => │ 3 │ 2 │ # => │ 4 │ 3 │ # => │ 5 │ 5 │ # => │ 6 │ 8 │ # => │ 7 │ 13 │ # => │ 8 │ 21 │ # => │ 9 │ 34 │ # => ╰───┴────╯