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

Re: while loop grammar question



On Sun, Dec 8, 2024, at 9:25 AM, Ray Andrews wrote:
> Yikes, gotchas within gotchas.  I expect something so fundamental is 
> pretty deeply coded so might have to be lived with.

I would be surprised if there were many users reliant on this
optional-loop-body behavior.


> Even given your 
> explanations above, it seems strange that the 'while' loop loops -- it 
> knows it's a loop but it doesn't understand it's own break condition.

It does understand its own break condition.  The issue is that the
break condition -- e.g., the command whose exit status matters --
is not where you think it is.  In a nutshell, this:

	while ((0)) {
		print foo
	}
	# ...

is equivalent to:

	while
		((0))
	do
		print foo
	done
	# ...

but this:

	while ((0))
	{
		print foo
	}
	# ...

effectively works like:

	while
		((0))
		{
			print foo
		}
		# ...
	do
		:
	done

(I'm using "# ..." to represent any subsequent commands.)

Remember that the test is a list of zero or more commands.  So the
last command of the script, whatever it is, controls the loop.


> So it is critical where the left brace is?

Yes.  If the left brace is on its own line, then it begins a { ... }
grouping command that is part of the test.  Consider that this is
valid (if silly):

	x=0
	while ((++x))
	{
		print testing
	}
	[[ x -le 3 ]]
	do
		print $x
	done

On the other hand, this is not valid:

	((++x)) {
		print testing
	}

which is why it could be repurposed for the short commands.


> As usual I'm thinking in C here.

An understandable impulse but one that does not serve you well when
thinking about shell scripting grammar.


> So what would be the hygienic form?  Stick with 'do/done' all the 
> time?

Yes.  It's predictable and largely portable (for those who care
about that, like I do).


> I'd prefer it throw an error consistently rather than accept the 
> 'for' form above, which I use all the time. At least I'd expect 'for' 
> and 'while' to have exactly the same grammar.

The difference is that "while" is followed by a list of arbitrary
commands that can be separated by LFs (for the short form, only the
final one has to be something like ((...)) or [[...]]).  With an
arithmetic "for" loop, the ((...)) construct is actually part of
the syntax, so there's no confusion about where the loop body begins.

-- 
vq




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