From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from primenet.com.au (ns1.primenet.com.au [203.24.36.2]) by inbox.vuxu.org (OpenSMTPD) with ESMTP id e6a33300 for ; Wed, 18 Dec 2019 05:24:12 +0000 (UTC) Received: (qmail 23335 invoked by alias); 18 Dec 2019 05:24:07 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: List-Unsubscribe: X-Seq: 45079 Received: (qmail 26239 invoked by uid 1010); 18 Dec 2019 05:24:07 -0000 X-Qmail-Scanner-Diagnostics: from wout2-smtp.messagingengine.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.102.1/25663. spamassassin: 3.4.2. Clear:RC:0(64.147.123.25):SA:0(-2.6/5.0):. Processed in 4.379615 secs); 18 Dec 2019 05:24:07 -0000 X-Envelope-From: d.s@daniel.shahaf.name X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: none (ns1.primenet.com.au: domain at daniel.shahaf.name does not designate permitted sender hosts) X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedufedrvddtkedgkeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfggtggugfgjfgesthektddttderjeenucfhrhhomhepffgrnhhi vghlucfuhhgrhhgrfhcuoegurdhssegurghnihgvlhdrshhhrghhrghfrdhnrghmvgeqne cukfhppeejledrudektddrheejrdduudelnecurfgrrhgrmhepmhgrihhlfhhrohhmpegu rdhssegurghnihgvlhdrshhhrghhrghfrdhnrghmvgenucevlhhushhtvghrufhiiigvpe dt X-ME-Proxy: Date: Wed, 18 Dec 2019 05:23:22 +0000 From: Daniel Shahaf To: Bart Schaefer Cc: zsh-workers@zsh.org Subject: Re: { exit } always { foo } Message-ID: <20191218052322.k744i7dwonwgeh33@tarpaulin.shahaf.local2> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: NeoMutt/20170113 (1.7.2) Bart Schaefer wrote on Tue, Dec 17, 2019 at 20:54:44 -0800: > On Tue, Dec 17, 2019 at 7:57 PM Daniel Shahaf 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 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