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

Re: why not promote the plague ? (brace|rc|alternative|modern) syntax



On Sat, Dec 14, 2024, at 2:54 PM, Mark J. Reed wrote:
> First, we have the standard syntax that works in any POSIX shell:
>
>     for var in val1 val2 val3; do command1; command2; done

While we're on the subject of parsing loops, here is some amusing
information about how historical shells handle the OG short `for'
loop, which implicitly uses the positional parameters.

https://www.in-ulm.de/~mascheck/various/bourne_args/#endnote


> The C-style *for* loop is not part of POSIX, but is common to bash, 
> ksh, and zsh:
>
>     for (( init; condition; increment )); do command1; command2; done

As an aside, the separator following ((...)) is optional for all
three shells.

	% bash -c 'for ((;;)) do break; done'
	% ksh -c 'for ((;;)) do break; done'
	% zsh -c 'for ((;;)) do break; done'
	%


> All of the above have an alternative syntax in Zsh that works 
> irrespective of the *SHORT_LOOPS* option, where you put the condition 
> (if any) in parentheses and the body in curly braces:
>
>     for var (val1 val2 val3) { command1; command2; }
>     while (command1; command2) { command3; command4; }
>     until (command1; command2) { command3; command4; }
>     if (command1; command2) { command3; command4; } else { command5; command6; }
>     for (( init; condition; increment )) { command1; command2; }
>     repeat $times { command1; command2; }
>
> NOTE: If the conditional command for while/until/if is a single ((...)) 
> or [[...]] test, you don't need the extra parentheses around it.

Other than the `for' variants, none of these (or the short forms
below) requires parentheses _per se_.  What they require is that
their conditions be, as zshmisc(1) so vaguely puts it, "suitably
delimited".  These are all valid:

	% if ! ( true ) { print true }
	% if [[ x ]] && { false } { print true }
	% if true; ! [[ x ]] { print true }
	% if print ignored | (( 0 )) { print true }
	%

So wrapping the condition in parentheses is not alternative
complex-command syntax, but merely standard subshell syntax
that slows loops to a crawl and breaks condition lists that
need to modify shell state.  Avoid.


> Finally, we have the Zsh "short" syntax, which works only with *setopt 
> SHORT_LOOPS*, and *only if the body is a single command*:
>
>     for var (val1 val2 val3) command1; 
>     while (command1; command2) command3
>     until (command1; command2) command3
>     if (command1; command2) command3;
>     for (( init; condition; increment )) command1;

Short-loop bodies aren't limited to single commands; they are
sublists, which POSIX calls AND-OR lists.  For example, this:

	% setopt SHORT_LOOPS
	% if { false } print foo && print bar
	%

works like this:

	if false
	then
		print foo && print bar
	fi

not this:

	if false
	then
		print foo
	fi && print bar


-- 
vq




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