zsh-users
 help / Atom feed
* dangerous behavior of while in zsh 5.6 ?
@ 2018-10-03 14:38 Marc Chantreux
  2018-10-03 15:28 ` Bart Schaefer
  0 siblings, 1 reply; 11+ messages in thread
From: Marc Chantreux @ 2018-10-03 14:38 UTC (permalink / raw)
  Cc: Zsh-Users List

hello people,

i switched to 5.6.2 and was really happy to see the
improvement of the alternative syntax.

thank you so much zsh-workers! i mean it! zsh is just awesome.

but there is an inconsistency in the behaviour that
is very dangerous and hard to easily spot in a large script:

a end of line after a condition is interpreted as an empty
true block so:

    while (( i-- ))
        print $i

should   mean:

    while (( i-- )) {print $i}

actually mean:

    while (( i-- )) {:}
    print $i

so it doesn't behave like the other loops:

    repeat 5 print $[i++]
    while (( i-- )) print $i

works ...

    repeat 5
        print $[i++]
    while (( i-- )) print $i

works ...

    repeat 5
        print $[i++]
    while (( i-- ))
        print $i

infinite loop. i think it's a bug. not sure :)

regards,
marc

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: dangerous behavior of while in zsh 5.6 ?
  2018-10-03 14:38 dangerous behavior of while in zsh 5.6 ? Marc Chantreux
@ 2018-10-03 15:28 ` Bart Schaefer
  2018-10-03 16:25   ` Marc Chantreux
  0 siblings, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2018-10-03 15:28 UTC (permalink / raw)
  To: Zsh Users; +Cc: Marc Chantreux

On Wed, Oct 3, 2018 at 7:47 AM Marc Chantreux <eiro@phear.org> wrote:
>
> a end of line after a condition is interpreted as an empty
> true block so:
>
>     while (( i-- ))
>         print $i

This is just a syntax error for me (or prints the PS2 prompt if
interactive), so I'm not sure how you're getting it to do anything.

This would certainly not be something new or different in 5.6.2.

In shell syntax, a newline is the same as a semicolon, so what you've
written should be the same as:

  while (( i-- )); print $i

To make that a complete loop statement you have to follow it with "do
... done" or something in braces or parens.

> should   mean:
>
>     while (( i-- )) {print $i}

No, it should mean

  while { (( i-- )); print $i; }

which will be an infiinte loop (if you ever supply the "do" block,
otherwise it's just a syntax error) because the exit status of the
loop condition { ... } will be that of the print statement, which is
never false.

> so it doesn't behave like the other loops:
>
>     repeat 5 print $[i++]
>     while (( i-- )) print $i

It's actually "repeat" that doesn't behave the same here, because
"repeat" has no test condition to follow the number of repetitions.
Thus

  repeat 5 ; print $[i++]

is

  repeat 5 { ; print $[i++]; }

Conversely the test condition for "while" is defined to be the whole
sequence of commands up to the keyword "do" or (with shortloops) one
of "{" or "(" or "((".  Commands in that sequence may be separated &&
or || or | or semicolon or newline.  This is not a bug, it's the way
the syntax is designed to work.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: dangerous behavior of while in zsh 5.6 ?
  2018-10-03 15:28 ` Bart Schaefer
@ 2018-10-03 16:25   ` Marc Chantreux
  2018-10-03 17:47     ` Daniel Shahaf
  2018-10-03 20:54     ` dangerous behavior of while in zsh 5.6 ? Bart Schaefer
  0 siblings, 2 replies; 11+ messages in thread
From: Marc Chantreux @ 2018-10-03 16:25 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

hello Bart,

> >     while (( i-- ))
> >         print $i
> This is just a syntax error for me (or prints the PS2 prompt if
> interactive), so I'm not sure how you're getting it to do anything.

i have the same behavior when interactive but no syntax error otherwise.

instead:

    {   repeat 2 print $[i++]
        while (( i-- )) print $i
    } |sed 10 | xargs

    > 0 1 1 0

    {   repeat 2
            print $[i++]
        while (( i-- ))
            print $i
    } |sed 10q | xargs

    > 0 1 1 0 -1 -2 -3 -4 -5 -6

but thanks to your enlightening explainations, i understand what's going
on and now have a short, gorgeous way to write a forever loop.

    nat () {
        local -i x=${1-0}
        while print $[x++]
    }

thank you very much, Bart.

regards.
marc

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: dangerous behavior of while in zsh 5.6 ?
  2018-10-03 16:25   ` Marc Chantreux
@ 2018-10-03 17:47     ` Daniel Shahaf
  2018-10-03 20:47       ` nat() in pure shell Marc Chantreux
  2018-10-03 20:54     ` dangerous behavior of while in zsh 5.6 ? Bart Schaefer
  1 sibling, 1 reply; 11+ messages in thread
From: Daniel Shahaf @ 2018-10-03 17:47 UTC (permalink / raw)
  To: zsh-users

Marc Chantreux wrote on Wed, 03 Oct 2018 18:25 +0200:
>     nat () {
>         local -i x=${1-0}
>         while print $[x++]
>     }

Compare:

yes '' | nl -ba

^ permalink raw reply	[flat|nested] 11+ messages in thread

* nat() in pure shell
  2018-10-03 17:47     ` Daniel Shahaf
@ 2018-10-03 20:47       ` Marc Chantreux
  2018-10-03 22:08         ` Daniel Shahaf
  2018-10-04 15:50         ` Bart Schaefer
  0 siblings, 2 replies; 11+ messages in thread
From: Marc Chantreux @ 2018-10-03 20:47 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: zsh-users

hello,


On Wed, Oct 03, 2018 at 05:47:19PM +0000, Daniel Shahaf wrote:
> Marc Chantreux wrote on Wed, 03 Oct 2018 18:25 +0200:
> >     nat () {
> >         local -i x=${1-0}
> >         while print $[x++]
> >     }
> 
> Compare:
> yes '' | nl -ba

wow ... good to know nl exists (i missed -nrz all the time). however

     yes '' | nl -ba

is a lot of extra caracters

nat () {
    local -i x=${1-0}
    while print $[x++]
}
nat | sed 2q | xxd

00000000: 300a 310a                                0.1.

awk 'BEGIN{ while (1) print i++ }' | sed 2q | xxd

00000000: 300a 310a                                0.1.

yes '' | nl -ba | sed 2q | xxd

00000000: 2020 2020 2031 090a 2020 2020 2032 090a       1..     2..

regards
marc



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: dangerous behavior of while in zsh 5.6 ?
  2018-10-03 16:25   ` Marc Chantreux
  2018-10-03 17:47     ` Daniel Shahaf
@ 2018-10-03 20:54     ` Bart Schaefer
  2018-10-03 21:06       ` Marc Chantreux
  1 sibling, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2018-10-03 20:54 UTC (permalink / raw)
  To: Zsh Users; +Cc: Marc Chantreux

On Wed, Oct 3, 2018 at 9:26 AM Marc Chantreux <eiro@phear.org> wrote:
>
> i have the same behavior when interactive but no syntax error otherwise.
>
> instead:
>
>     {   repeat 2 print $[i++]
>         while (( i-- )) print $i
>     } |sed 10 | xargs

This shows a critical missing bit of detail from your original
message:  The while loop is inside a { } expression.  The parser
treats the close-brace as terminating the loop with an empty body.  If
this had been in a script file with end-of-file at that point, you
would have received the syntax error.

% { while false
cursh while> }
%

This potentially does indicate a parsing problem in 5.6, because in 5.0:

% { while false
cursh while> }
zsh: parse error near `}'

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: dangerous behavior of while in zsh 5.6 ?
  2018-10-03 20:54     ` dangerous behavior of while in zsh 5.6 ? Bart Schaefer
@ 2018-10-03 21:06       ` Marc Chantreux
  0 siblings, 0 replies; 11+ messages in thread
From: Marc Chantreux @ 2018-10-03 21:06 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

hello,

    repeat 2 print $[i++]
    while ((i--))
        print $i

> >     {   repeat 2 print $[i++]
> >         while (( i-- )) print $i
> >     } |sed 10 | xargs

> This shows a critical missing bit of detail from your original
> message:  The while loop is inside a { } expression.

the way i wrote it was only to demonstrate but this is another example:

    # grep -n . /tmp/a.zsh
    1:repeat 2 print $[i++]
    2:while ((i--))
    3:    print $i
    # zsh /tmp/a.zsh | sed 10q
    0
    1
    1
    0
    -1
    -2
    -3
    -4
    -5
    -6

regards
marc

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: nat() in pure shell
  2018-10-03 20:47       ` nat() in pure shell Marc Chantreux
@ 2018-10-03 22:08         ` Daniel Shahaf
  2018-10-03 23:23           ` Marc Chantreux
  2018-10-08 10:38           ` Vincent Lefevre
  2018-10-04 15:50         ` Bart Schaefer
  1 sibling, 2 replies; 11+ messages in thread
From: Daniel Shahaf @ 2018-10-03 22:08 UTC (permalink / raw)
  To: Marc Chantreux; +Cc: zsh-users

Marc Chantreux wrote on Wed, 03 Oct 2018 22:47 +0200:
> On Wed, Oct 03, 2018 at 05:47:19PM +0000, Daniel Shahaf wrote:
> > Marc Chantreux wrote on Wed, 03 Oct 2018 18:25 +0200:
> > >     nat () {
> > >         local -i x=${1-0}
> > >         while print $[x++]
> > >     }
> > 
> > Compare:
> > yes '' | nl -ba
> 
> wow ... good to know nl exists (i missed -nrz all the time). however
> 
>      yes '' | nl -ba
> 
> is a lot of extra caracters
> 
> 00000000: 2020 2020 2031 090a 2020 2020 2032 090a       1..     2..

Then pipe it to 'xargs -n1' or tr(1) or sed(1) or ...

While at it, 'pr -tn' is another line-numbering command.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: nat() in pure shell
  2018-10-03 22:08         ` Daniel Shahaf
@ 2018-10-03 23:23           ` Marc Chantreux
  2018-10-08 10:38           ` Vincent Lefevre
  1 sibling, 0 replies; 11+ messages in thread
From: Marc Chantreux @ 2018-10-03 23:23 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: zsh-users

On Wed, Oct 03, 2018 at 10:08:34PM +0000, Daniel Shahaf wrote:
> >      yes '' | nl -ba
> > 
> > is a lot of extra caracters
> > 
> > 00000000: 2020 2020 2031 090a 2020 2020 2032 090a       1..     2..
> 
> Then pipe it to 'xargs -n1' or tr(1) or sed(1) or ...

yes .. but if i really want to avoid the shell version, i'll go to awk:

    awk -vi=${1-0} 'BEGIN { while (1) print i++ }' |sed 5q

> While at it, 'pr -tn' is another line-numbering command.

so is awk :)

    print -l {a..c} | awk -vi=${1-0} '{print i++,$0}'

regards
marc

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: nat() in pure shell
  2018-10-03 20:47       ` nat() in pure shell Marc Chantreux
  2018-10-03 22:08         ` Daniel Shahaf
@ 2018-10-04 15:50         ` Bart Schaefer
  1 sibling, 0 replies; 11+ messages in thread
From: Bart Schaefer @ 2018-10-04 15:50 UTC (permalink / raw)
  To: Marc Chantreux; +Cc: Daniel Shahaf, Zsh Users

> > Marc Chantreux wrote on Wed, 03 Oct 2018 18:25 +0200:
> > >     nat () {
> > >         local -i x=${1-0}
> > >         while print $[x++]
> > >     }

You should not count on this continuing to work, it's definitely a bug
that you don't get a parse error there.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: nat() in pure shell
  2018-10-03 22:08         ` Daniel Shahaf
  2018-10-03 23:23           ` Marc Chantreux
@ 2018-10-08 10:38           ` Vincent Lefevre
  1 sibling, 0 replies; 11+ messages in thread
From: Vincent Lefevre @ 2018-10-08 10:38 UTC (permalink / raw)
  To: zsh-users

On 2018-10-03 22:08:34 +0000, Daniel Shahaf wrote:
> While at it, 'pr -tn' is another line-numbering command.

But pr will truncate the number when it is too large for the width.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, back to index

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-03 14:38 dangerous behavior of while in zsh 5.6 ? Marc Chantreux
2018-10-03 15:28 ` Bart Schaefer
2018-10-03 16:25   ` Marc Chantreux
2018-10-03 17:47     ` Daniel Shahaf
2018-10-03 20:47       ` nat() in pure shell Marc Chantreux
2018-10-03 22:08         ` Daniel Shahaf
2018-10-03 23:23           ` Marc Chantreux
2018-10-08 10:38           ` Vincent Lefevre
2018-10-04 15:50         ` Bart Schaefer
2018-10-03 20:54     ` dangerous behavior of while in zsh 5.6 ? Bart Schaefer
2018-10-03 21:06       ` Marc Chantreux

zsh-users

Archives are clonable: git clone --mirror http://inbox.vuxu.org/zsh-users

Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.zsh.users


AGPL code for this site: git clone https://public-inbox.org/ public-inbox