Thread (1 message) 1 message, 1 author, 2016-06-15

Re: [PATCH] Supplant the "while case ... break ;; esac" idiom

From: David Kastrup <hidden>
Date: 2016-06-15 22:43:36

Junio C Hamano [off-list ref] writes:
David Kastrup [off-list ref] writes:
quoted
I am somewhat taken aback that a commit message considered offensive
(though I still have a problem understanding why and certainly did not
intend this) has been committed into master without giving me a chance
to amend it.
Heh, that's simple.  I changed my mind ;-)

When A and B test for preconditions, and C, D, and E are
operations with error reports as their side effects, we can
write our loop in these forms:

 (1) while A && B && C && D && E || false; do :; done
 (2) while A && B && C && D && E || break; do :; done
 (3) while A && B; do C && D && E || break; do :; done
 (4) while :; do A && B && C && D && E || break; done

and all of them are equivalent.

But obviously the only sane version is (3).
Uh, it is the only version with a syntax error.
If your complaint were against things like (1) and (2), I would have
completely agreed with you.  If you want "effects", you do so
between do and done.  Although you can use break between do and done
if you need to conditionally break out of the loop after causing
some effect there, between while and do is where you are only
supposed to decide if you want to break out of the loop without
causing "effects".

But what you were complaining about was different.
Basically

while A && B || break; do C && D && E || break; done
If we were to ignore broken shells that do not return success
from a case statement with no matching pattern, the following
two are equivalent:

	while case "$sth" in foo) break ;; esac; do ...; done
	while case "$sth" in foo) false ;; esac; do ...; done

Their "case" are used to decide if you want to break out of the
loop; the former is (1) being a bit more explicit, and (2) used
to be a bit more efficient when false was not built-in.
As a completely irrelevant side note: the autoconf documentation
mentions that "false" is more portable than "true" since calling it
returns a non-zero exit status even when it is not installed or
built-in.
Now the latter reason is mostly historical and it is not a valid
reason to choose the former over the latter anymore.  But that does
not make it any more confusing than the latter to a person who knows
what "break" means in a loop.  An explicit 'break' is still more,
eh,... explicit ;-)

But the "break" never was the issue.  Return value of "case" was.
I guess this has been a misunderstanding: for me, personally, the
break was the issue: I don't like breaking out of a condition, since
breaking for me is an action.  I just used the fact that the BSD
shells happen not to grok the constructs (and actually through a
somewhat similar confusion between condition and action) to leverage
my dislike of this construct and propose a patch.
The reason I took your patch and proposed commit log message
(almost) as-is was because you rewrote "case" to "test".
Uhm, ok.  It was a case of realizing "hm, this does not really look
much nicer" before I chose to switch to "test".  In fact, there is one
case statement remaining which I rewrote in the previously discussed
manner, and it did not strike me as being much prettier.  So maybe I
somewhat misjudged the core of my offended sense of aesthetics, but
the impetus of the discussion still carried into the commit message.

Alea iacta est ("The SHA-1 has been established").

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help