On Wed, May 3, 2023 at 7:46 AM Sebastian Gniazdowski wrote: > > I was looking at some of my old patches and stumbled upon this one > which implements mksh' ${|func;} substitution. > [...] Original thread: > https://zsh.org/mla/workers/2019/msg00768.html I'm not going to try to recapitulate all the objections/discussions from that thread, but here are some thoughts. > [...] The old thread went > over a complex (x) flag [but] ${!func;} doesn't block us from adding a > more advanced x-flag in the future. [...] An argument put forward in the code comments in this most recent patch, namely that adding an (x) flag requires further revisions of "14.3.3 Rules" in the documentation, does have some merit. It would be complicated to combine (x) with other flags in the same substitution step, and even more convoluted to try to explain it. I think it's preferable to treat it more like a command substitution ala $(...). > To recall - the ${|func;} substitution runs function "func" and > substitutes (returned string in…) $REPLY after it has completed, > without (!) doing forks, which is a performance and functionality > benefit over currently available equivalent: $(func;print -rn -- > $REPLY). One of the significant bits from the previous thread was the notion that the mksh syntax is actually ${|command} rather than just limited to functions. I looked at Sebastian's later patch (workers/44742) that tried to implement this, but I think calling bin_eval() isn't necessary. Also in that thread Stephane points out that it would be ideal if (paraphrasing his example) "${| echo { }" were parsed similarly to "{ echo { }" and that to do so would require changes to the parser, not just to the substitution process. However, we can get most of the way there with what Sebastian has proposed and any future parser revisions to take this out of paramsubst() would not (I think) need to invalidate code written to this first approximation. The other thing that bothered me about the idea is the hardcoded reliance on $REPLY, so I took a stab at something to address that. Given the foregoing, here's a proposed alternative to Sebastian's patch. Formal doc and tests pending reaction. Informally, ${|code} passes the code through execstring() and then substitutes the value of $REPLY. ${|VAR|code} passes code through execstring() and then substitutes the value of $VAR. This even works where VAR includes a namespace prefix or a subscript expression, but VAR must otherwise look like a scalar parameter reference. The main limitation on code so interpolated is that it can't contain unquoted { or } ... multi-line code is OK. A remark about the last hunk of the patch: I kept this from Sebastian's original patch, it has the effect that ${|code} never appears to be an unset parameter, even if that code does not set REPLY. I'm not certain that's actually necessary.