bug-bash
[Top][All Lists]
Advanced

[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).




reply via email to

[Prev in Thread] Current Thread [Next in Thread]