zsh-workers
 help / color / mirror / code / Atom feed
* { exit } always { foo }
@ 2019-12-18  3:56 Daniel Shahaf
  2019-12-18  4:54 ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Shahaf @ 2019-12-18  3:56 UTC (permalink / raw)
  To: zsh-workers

The documentation of the try-always construct says:

    An tt(exit) command (or a tt(return) command executed at the outermost
    function level of a script) encountered in tt(try-list) does em(not) cause
    the execution of var(always-list).  Instead, the shell exits immediately
    after any tt(EXIT) trap has been executed.

However, A01grammar.ztst expects the always-list to be run:

  723	  (
  724	  mywrap() { echo BEGIN; true; echo END }
  725	  mytest() { { exit 3 } always { mywrap }; print Exited before this }
  726	  mytest
  727	  print Exited before this, too
  728	  )
  729	3:Exit and always block with functions: simple
  730	>BEGIN
  731	>END

Which is correct, the manual or the test?

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

* Re: { exit } always { foo }
  2019-12-18  3:56 { exit } always { foo } Daniel Shahaf
@ 2019-12-18  4:54 ` Bart Schaefer
  2019-12-18  4:59   ` Bart Schaefer
  2019-12-18  5:23   ` Daniel Shahaf
  0 siblings, 2 replies; 7+ messages in thread
From: Bart Schaefer @ 2019-12-18  4:54 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: zsh-workers

On Tue, Dec 17, 2019 at 7:57 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Which is correct, the manual or the test?

I think both are, although the wording in the doc might be clearer.
This is the important bit (my capitals):

>     An tt(exit) command (or a tt(return) command executed AT THE OUTERMOST
>     function LEVEL of a script) encountered in tt(try-list) does em(not) cause
>     the execution of var(always-list).  Instead, the shell exits immediately
>     after any tt(EXIT) trap has been executed.

The word "function" there is unfortunate because it doesn't mean a
shell function.

In this line:
>   725     mytest() { { exit 3 } always { mywrap }; print Exited before this }

The always block is NOT at the outermost level, so the shell does not
exit immediately.  "Outermost" means that there IS NO surrounding
function scope.  Thus in the following case:

 (
  mywrap() { echo BEGIN; true; echo END }
  { exit 3 } always { mywrap }; print Exited before this
 )

The always block is not executed and mywrap isn't called.  As soon as
you put the "always" inside the "mytest" scope, that rule no longer
applies.

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

* Re: { exit } always { foo }
  2019-12-18  4:54 ` Bart Schaefer
@ 2019-12-18  4:59   ` Bart Schaefer
  2019-12-18  5:23   ` Daniel Shahaf
  1 sibling, 0 replies; 7+ messages in thread
From: Bart Schaefer @ 2019-12-18  4:59 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: zsh-workers

On Tue, Dec 17, 2019 at 8:54 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> The word "function" there is unfortunate because it doesn't mean a
> shell function.

Well, strictly I guess it does mean a shell function because that's
the only way to introduce another scope, but it's confusing to think
of "the level where no shell function has been introduced yet" as a
"function level".  It's sort of like calling the sidewalk in front of
a building the "outermost floor".

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

* Re: { exit } always { foo }
  2019-12-18  4:54 ` Bart Schaefer
  2019-12-18  4:59   ` Bart Schaefer
@ 2019-12-18  5:23   ` Daniel Shahaf
  2019-12-19 15:28     ` Daniel Shahaf
  1 sibling, 1 reply; 7+ messages in thread
From: Daniel Shahaf @ 2019-12-18  5:23 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers

Bart Schaefer wrote on Tue, Dec 17, 2019 at 20:54:44 -0800:
> On Tue, Dec 17, 2019 at 7:57 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> >
> > Which is correct, the manual or the test?
> 
> I think both are, although the wording in the doc might be clearer.
> This is the important bit (my capitals):
> 
> >     An tt(exit) command (or a tt(return) command executed AT THE OUTERMOST
> >     function LEVEL of a script) encountered in tt(try-list) does em(not) cause
> >     the execution of var(always-list).  Instead, the shell exits immediately
> >     after any tt(EXIT) trap has been executed.

The way I read this is, it says that such-and-such will happen whenever
_either_ of the following two constructs is seen:

- 'exit' is invoked by try-list (possibly in a deep callee)

- 'return' is invoked, outside of any function, in a try-list

That is, the "at the outermost level" qualifier applies only to 'return', not
to 'exit'.  This interpretation is supported by the parentheses.  (This is one
of the rare cases in which English is explicit about its syntactic precedece rules.)

Under this reading, the docs promise that the test's behaviour will be the same regardless
of whether or not the 'exit' happens to be in a function.

> In this line:
> >   725     mytest() { { exit 3 } always { mywrap }; print Exited before this }
> 
> The always block is NOT at the outermost level, so the shell does not
> exit immediately.  "Outermost" means that there IS NO surrounding
> function scope.  Thus in the following case:
> 
>  (
>   mywrap() { echo BEGIN; true; echo END }
>   { exit 3 } always { mywrap }; print Exited before this
>  )
> 
> The always block is not executed and mywrap isn't called.  As soon as
> you put the "always" inside the "mytest" scope, that rule no longer
> applies.

Good catch.  Based on the manual, I would have expected such a difference to
manifest if the two cases had used 'return 3', but not if they used 'exit 3'.

Furthermore, it makes intuitive sense for 'return' to behave in one way inside
a function, and in another way — like 'exit' — when not inside a function; but
I don't immediately see why it makes sense for 'exit' to change behaviour
depending on when it's inside a function or not.  Compare:

1.
    mywrap() { echo BEGIN; true; echo END }
        { exit 3 } always { mywrap }; print Exited before this

2.
    mywrap() { echo BEGIN; true; echo END }
    (){ { exit 3 } always { mywrap }; print Exited before this }

So, personally, I would find it more intuitive to change the implementation to
match the documentation, than the other way around.

Bart Schaefer wrote on Tue, Dec 17, 2019 at 20:59:01 -0800:
> On Tue, Dec 17, 2019 at 8:54 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
> >
> > The word "function" there is unfortunate because it doesn't mean a
> > shell function.
> 
> Well, strictly I guess it does mean a shell function because that's
> the only way to introduce another scope, but it's confusing to think
> of "the level where no shell function has been introduced yet" as a
> "function level".  It's sort of like calling the sidewalk in front of
> a building the "outermost floor".

It's intuitive enough to me.  It's pretty common in math contexts, too: for
example, one can scale down quadratic equations and linear equations to
zeroth-degree equations (a₀⋅x⁰ = 0, solve for $x$).  Makes perfect sense.
(No promises about usefulness, though.)

Cheers,

Daniel

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

* Re: { exit } always { foo }
  2019-12-18  5:23   ` Daniel Shahaf
@ 2019-12-19 15:28     ` Daniel Shahaf
  2019-12-19 15:37       ` Peter Stephenson
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Shahaf @ 2019-12-19 15:28 UTC (permalink / raw)
  To: zsh-workers

Daniel Shahaf wrote on Wed, 18 Dec 2019 05:23 +00:00:
> So, personally, I would find it more intuitive to change the implementation to
> match the documentation, than the other way around.

I'll wait a bit more for feedback.  If the decision ends up being to change the
implementation to match the documentation, I'll at least document it as
a bug/incompatibility, or maybe fix it if I manage that.

I found this while testing patches related to Martijn's bug (44007).  Once
this bug is resolved I'll get back to 44007.

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

* Re: { exit } always { foo }
  2019-12-19 15:28     ` Daniel Shahaf
@ 2019-12-19 15:37       ` Peter Stephenson
  2019-12-19 16:05         ` Daniel Shahaf
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Stephenson @ 2019-12-19 15:37 UTC (permalink / raw)
  To: zsh-workers

On Thu, 2019-12-19 at 15:28 +0000, Daniel Shahaf wrote:
> Daniel Shahaf wrote on Wed, 18 Dec 2019 05:23 +00:00:
> > 
> > So, personally, I would find it more intuitive to change the implementation to
> > match the documentation, than the other way around.
> I'll wait a bit more for feedback.  If the decision ends up being to change the
> implementation to match the documentation, I'll at least document it as
> a bug/incompatibility, or maybe fix it if I manage that.

I don't think it's that big a deal either way as long as the inconsistency
gets fixed; I'd be happy to leave it to what ever feels most natural if you're
using the feature in question.

cheers
pws


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

* Re: { exit } always { foo }
  2019-12-19 15:37       ` Peter Stephenson
@ 2019-12-19 16:05         ` Daniel Shahaf
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Shahaf @ 2019-12-19 16:05 UTC (permalink / raw)
  To: zsh-workers

Peter Stephenson wrote on Thu, 19 Dec 2019 15:37 +00:00:
> On Thu, 2019-12-19 at 15:28 +0000, Daniel Shahaf wrote:
> > Daniel Shahaf wrote on Wed, 18 Dec 2019 05:23 +00:00:
> > > 
> > > So, personally, I would find it more intuitive to change the implementation to
> > > match the documentation, than the other way around.
> > I'll wait a bit more for feedback.  If the decision ends up being to change the
> > implementation to match the documentation, I'll at least document it as
> > a bug/incompatibility, or maybe fix it if I manage that.
> 
> I don't think it's that big a deal either way as long as the inconsistency
> gets fixed; I'd be happy to leave it to what ever feels most natural if you're
> using the feature in question.

I think there are actually two separate questions here:

- Whether 'return outside of any function' should be equivalent to 'exit'

- Whether the always-list should be run if the try-list does an exit

I'm not sure what my answers to these questions any more.

For that matter, should the always-list run if a SIGINT is received during the
try-list?  What about SIGQUIT?  The documentation only says the always-list
will be executed in case of "a condition such as a syntax error which causes
the shell to abort execution [...]".

Hmm…

Daniel

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

end of thread, other threads:[~2019-12-19 16:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-18  3:56 { exit } always { foo } Daniel Shahaf
2019-12-18  4:54 ` Bart Schaefer
2019-12-18  4:59   ` Bart Schaefer
2019-12-18  5:23   ` Daniel Shahaf
2019-12-19 15:28     ` Daniel Shahaf
2019-12-19 15:37       ` Peter Stephenson
2019-12-19 16:05         ` Daniel Shahaf

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).