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.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FROM,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 739e070d for ; Sat, 7 Sep 2019 20:20:37 +0000 (UTC) Received: (qmail 205 invoked by alias); 7 Sep 2019 20:20:32 -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: 44741 Received: (qmail 26076 invoked by uid 1010); 7 Sep 2019 20:20:32 -0000 X-Qmail-Scanner-Diagnostics: from mail-wr1-f67.google.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.101.2/25559. spamassassin: 3.4.2. Clear:RC:0(209.85.221.67):SA:0(-2.0/5.0):. Processed in 1.751899 secs); 07 Sep 2019 20:20:32 -0000 X-Envelope-From: stephane.chazelas@gmail.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _netblocks.google.com designates 209.85.221.67 as permitted sender) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to:user-agent; bh=M3AtqsJqf78a7sOCRNi+0cg/VhqjCwUEqRVc1wt0cd4=; b=O4DXWSf8mpmz1gotYlj+v1qBVnm6v6bDs1AV9GfboWFdfGNQiSssMRSqkp9FIcSoo4 xbgOYHYiJFgPT9aKoLvH+y4jXeWa0ku0a7U4aolbPiPUKXyZ3TJMzZkoX0HYg+zSBVVe wfLVbTDNwEytMrJTWs4J1b6J9V49Z1GeHz1l5vYijJQSa979DiVuvYdlHLSQNkWDxw2E jGTTD3TFRCnpPIWy4G+VtrXo6k9pKHtCArcLTCm+Yqfdgqe+oK0+yWU7t+TIe0Ya2p2M Z7AHRA6UCeC3Ug4VUMH/IlWWUJaH5dXPCTzzhS0wqj33sU7HYsy6xI3wXvbPxtm4c31T 9Ulg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id :mail-followup-to:references:mime-version:content-disposition :in-reply-to:user-agent; bh=M3AtqsJqf78a7sOCRNi+0cg/VhqjCwUEqRVc1wt0cd4=; b=Qz3LKJ4d30tC6z0LtORw5kvMu+xkghdHMh+QCyk2NpKdTA8FYv3CEPzGN5AxM5rbav Gtnv9ZVI55d8loTZz3fw6oV829cXAnrGHS/Ltjl3/LKfo3eefswswvppPE74UuUBA04A N3sEivE2XxHg6QjRXtpnWHj7L4AEBnOuMG1Du7za8fgwJqzNL1TRSr/nnbf4DVr+qYli U0qa5xDSMBGMQfHJDyFJoSQt7pAtr72Z2x41+vBsC+Vm0+aATG8cXdBJ6s+nJMGSY1Gz nWuw+VvklJimWYV5Kz1ToAb9d4EqmIF1LA2hnM6BC771YhBHbUbFiMNANfU6qVtkqMzs ZVoA== X-Gm-Message-State: APjAAAV/4l4I/kXMWAy2GghSJAJLyifgmHD3ouNOKelpz+FNayevBi+E EndSH9RG0goqDj4oAF2rZgovFydbDrQ= X-Google-Smtp-Source: APXvYqyyKSqfuVZnMJeICGu9UqeadbIqkhZXOJMoqzQEHNRGbHz2xF8CxWiwgy/PbaXbVUDvuay1yw== X-Received: by 2002:a5d:640f:: with SMTP id z15mr11120845wru.217.1567887596774; Sat, 07 Sep 2019 13:19:56 -0700 (PDT) Date: Sat, 7 Sep 2019 21:19:54 +0100 From: Stephane Chazelas To: Sebastian Gniazdowski Cc: Zsh hackers list Subject: Re: [PATCH] Support the mksh's ${|func;} substitution Message-ID: <20190907201954.dn2nve65wqk4muvc@chaz.gmail.com> Mail-Followup-To: Sebastian Gniazdowski , Zsh hackers list References: <20190907150741.jwztdoslrvk5j7nk@chaz.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: NeoMutt/20171215 2019-09-07 20:09:57 +0200, Sebastian Gniazdowski: > On Sat, 7 Sep 2019 at 17:07, Stephane Chazelas > wrote: > > Note that mksh's operator can do ${|REPLY=value}, it's not > > limited to functions. > > Ok, true, it can also run binary commands. > > > The ; is also not necessary > > I think that this is undocumented feature, as the docs say: > > "Another variant of substitution are the valsubs (value substitutions) > ${|command;} which are also executed in the current environment, like > funsubs, but share their I/O with the parent; instead, they evaluate > to whatever the, initially empty, expression-local variable REPLY is > set to within the commands." [...] Those operators are shaped after the ksh93 ${ cmdsubst;} operator. ksh93 man page also mentions the ; there, but it's not necessary either. In ksh93, ${(uname)} or ${ uname } (which for those who wouldn't be familiar with those is the same as $(cmdsubst) but without creating a subshell environment) also work. That is the { must be delimited from the following code, and } delimited from the previous code. The ${ cmd;} is reminiscent of { cmd;}, it makes sense to document that form as it makes it more obvious what we're talking about, but just like {(cmd)} also works ${(cmd)} works as well (in ksh93, not in mksh). { cmd} doesn't work, but ${ cmd} does though (in mksh, not in ksh93 where you need ${ cmd }). That discrepancy causes confusion: $ ksh -c '{ echo }; }' } $ ksh -c 'echo ${ { echo }; }; }' ksh: syntax error at line 1: `}' unexpected (you can not longer use a bare "}" inside ${ ...; }) $ mksh -c 'echo ${ { echo }; echo x } y' x y $ ksh -c 'echo ${ { echo }; echo x } y' ksh: syntax error at line 1: `{' unmatched $ mksh -c '{ echo x }' mksh: syntax error: unmatched '{' It is quite messy. In ksh93 ${ print foo;} is efficient because in that case "print" doesn't write "foo\n", the "foo" makes up the result of the expansion without any I/O being made. And it's also the case in ${ myfunction; }. ksh93 only ever forks for executing external commands or in pipelines. When inside a subshell, ksh93 adds the would-be-output data to the command-substitution-to-be ksh93 was a complete rewrite (compared to ksh88). For mksh to be able to do that, it would probably have had to be completely rewritten as well. Instead, in mksh, for ${ code; }, for the code not to run in a subshell, the code's output is written to a temp file which is read afterwards, which is less efficient as it involves I/O. I suppose that's why the ${| cmd;} variant that uses the $REPLY variable to transfer the data and avoids I/O was introduced (you'd still get I/O through a pipe if you do ${|REPLY=$(print test)}. [...] > > With those fixed, i.e. when it's really like mksh's ${|code}, > > I'd agree the feature could be useful, but I suspect that would > > be harder to implement as it would mean changing the parsing. > > The parsing would have to be changed to prevent the "=" in function names? [...] No, I meant that you'd need the parser to handle that case of a pseudo-command group (a {any shell code here} but with {| instead of {)). So you can do: echo ${| whatever $(...) for i do ... done} Whether it would actually be difficult or not I can't comment, I've not looked at the parser code. Having an operator that *only* invokes a function to do an expansion is less useful IMO. That just sound like a very limited form of command substitution where you could have done a more complete form by allowing any code instead of just one function invocation without argument. Note that mksh calls it "function substitution" not because you can invoke a function within it but because the code in ${ code; } is like in a function body, where it can have a local scope, call return, but is a bit buggy when it comes to positional parameters: $ mksh -c 'echo "$@"; : "${ shift}"; echo "$@"' sh 1 2 1 2 sh 2 -- Stephane