Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: "break" and functions



On Fri, Mar 29, 2024 at 10:38 AM Oliver Kiddle <opk@xxxxxxx> wrote:
>
> My expectation would have been for either an error message saying
>   break: not in while, until, select, or repeat loop`
> or that because the break is run before the builtin that the builtin
> would never get to run.

The latter was my expectation; I think the break is inside the loop.

Skipping ahead:
> It also rather surprises me that the break here even works:
>
>   br() { break }
>   while : ; do
>     br
>   done

% setopt localloops
% br() { break }
% repeat 3 br
zsh: `break' active at end of function scope
zsh: `break' active at end of function scope
zsh: `break' active at end of function scope
% unsetopt localloops
% repeat 3 br
%

> But the implementation of break is just putting
> a value in the breaks integer variable so I guess that variable isn't
> checked until after the builtin is run.

Right; since the break occurs in prefork() we're already deeper in the
execXXX() call stack than anywhere the variable is checked.  The
function call re-enters that stack closer to the top, and finds the
setting.

> The anonymous function is
> perhaps a two-stage process for defining and then running. Note:
>   while :; do; () { echo hello } > ${|REPLY=x;break}; done
> creates an empty file named x.

Again, prefork() ... the redirections also occur before breaks is
checked.  Although this:
  echo xx > ${|REPLY=x;exit}
does bail out before completing the redirect, whereas this:
  echo xx > ${|REPLY=x;return}
does not.

> When suggesting the test, the exact behaviour was not something I cared
> strongly about provided it wasn't seg fault, infinite loop or similar.

Yes, I understand.  I considered testing this way for future-proofing:

repeat 3 V=${|REPLY=x; break}
print $V

I ended up deciding that it was reasonable to leave the "echo ${|...}"
as an ad-hoc regression test in the event builtins do start
"break"-ing.

> In the case of
>   repeat 3 print c*(oe:'break':)
> it might be a useful feature if break applied to the internal loop over
> globbed files causing print to run but only with those files that were
> matched so far.

IIRC the entire glob loop finishes and then any (e) actions are
applied to the resulting list.  So "matched so far" is not well
defined.  I believe the only way to stop the internal loop "early" is
the (Y) qualifier.




Messages sorted by: Reverse Date, Date, Thread, Author