[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Why should `break' and `continue' in functions not break loops runni
From: |
Robert Elz |
Subject: |
Re: Why should `break' and `continue' in functions not break loops running outside of the function? |
Date: |
Sat, 30 Oct 2021 23:07:24 +0700 |
What POSIX says about this (which you probably know already) is:
A loop shall enclose a break or continue command if the loop
lexically encloses the command. A loop lexically encloses a
break or continue command if the command is:
[and just paraphrasing the conditions]
- same exxecution environment (ie: not in a subshell)
- inside a compound list associated with a loop (including
the test list for while/until)
- not in the body of a function ...
(more or less the obvious useful definition of lexically enclosing).
That is the case in which break & continue are required to work.
It goes on to say:
If n is greater than the number of lexically enclosing loops
and there is a non-lexically enclosing loop in progress in the
same execution environment as the break or continue command, it is
unspecified whether that loop encloses the command.
In your example, the number of lexically enclosing loops is 0, 'n' is 1,
so the shell is allowed to break from the loop, but not required to.
Or in other words, you should not write code like that, because it
is not guaranteed to work.
oguzismailuysal@gmail.com said:
| `break' is not a keyword in the shell, but a special command.
That's true. However, 99% of script writers don't see it that way,
they believe it is just like "if" or "while" or "done" or "return".
That's why the "This is counterintuitive." I would guess - in most
cases, the issue isn't quite like yours, but more like
f() {
for x in a b c; do
for y in 1 2 3; do
case "$x$y" in
(b3) break;;
(a2) continue 2;;
(c1) break 3;;
esac
done
done
}
and then called something like
for i in 1 2 3 4 5 6
do
echo $i; f
done
and people wonder why that loop never iterates the 2nd time (prints just 1).
All this because the script author probably thought that they were
writing C, and the b3 break is for the case statement, a2 continue
is the y loop, and c1 break the x loop...
They can be taught that that's wrong, break/continue do nothing for
case statements, and don't count them - but they simply refuse to believe
that whatever happens inside the function should affect the caller's
flow - an error from the "break 3" is something they can understand,
as is just ignoring the "overflow", but not more than that.
For people who don't believe that all programming languages should work
the same way (usually the same way as the one they learned first) this
isn't necessarily as important - but that's a tiny majority of people.
kre
ps: the NetBSD shell continues to work the way that you want, and does
so by deliberate choice - our test suite has a whole stack of tests to
make sure this continues to all work "correctly" (doesn't accidentally
get changed).