zsh-workers
 help / color / mirror / code / Atom feed
* Nofork ${{var}...} edge cases
@ 2024-03-27 18:57 Bart Schaefer
  2024-03-27 22:22 ` Oliver Kiddle
  2024-03-28  0:29 ` Mikael Magnusson
  0 siblings, 2 replies; 7+ messages in thread
From: Bart Schaefer @ 2024-03-27 18:57 UTC (permalink / raw)
  To: Zsh hackers list

Just seeking opinions:

Should ${{} true} (empty variable name) result in "bad substitution"?
Otherwise it's all side-effects, because nothing will be substituted.
The prior ${|| true} form was a parse error.

Should ${{var}} be a "bad substitution", or print a warning about an
empty command?  Otherwise it just substitutes $var.

What about ${{var};} or ${{var}{}} etc.?

Given:
% REPLY=123
Currently this works:
% print ${{REPLY} REPLY=abc}
abc
%
But the following does not substitute "b":
% print ${{REPLY[2]} REPLY=abc}
2
%

That's because REPLY is implicitly local to the substitution but
REPLY[2] becomes linked to the caller's $REPLY.  (This is a problem
with |REPLY[2]| as well, not new with the braces.)  With any other
name than REPLY, the subscript works as expected.  How much effort is
it worth putting into fixing this?  I would expect it more typical to
do:
% print ${${| REPLY=abc}[2]}
b
%

Or we could declare ${{REPLY}...} as NOT synonymous with ${|...} and
localize REPLY only in the latter of those.  That might actually make
more sense.

In an earlier thread, Oliver asked:
> Given that the ${|var| ... } form appears to create a function-like
> scope, should var perhaps be auto-declared local for that scope and the
> local value be substituted?

Among the reasons I listed for not doing this, I forgot to mention
that subscripts are allowed and you can't localize a subscripted
parameter.

I'd like to resolve these before I update the Doc.


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

* Re: Nofork ${{var}...} edge cases
  2024-03-27 18:57 Nofork ${{var}...} edge cases Bart Schaefer
@ 2024-03-27 22:22 ` Oliver Kiddle
  2024-03-28  1:00   ` Bart Schaefer
  2024-03-28  0:29 ` Mikael Magnusson
  1 sibling, 1 reply; 7+ messages in thread
From: Oliver Kiddle @ 2024-03-27 22:22 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list

Bart Schaefer wrote:
> Just seeking opinions:
>
> Should ${{} true} (empty variable name) result in "bad substitution"?

Given that ${} just outputs nothing, the current behaviour of also
outputting nothing is entirely consistent.

That is just a zshism, however:
  ksh: syntax error: `}' unexpected
  bash: ${}: bad substitution
  /bin/sh: ${}: Bad substitution

I prefer zsh's behaviour here - ignoring the error - but would guess the
reason for it may be related to the support for nested substitutions. And
while uses of ${} alone are rare, variants such as ${:-xx} are useful.
Your patch doesn't allow a substitution inside the {}, however so nested
substitutions are not a reason here.

> Otherwise it's all side-effects, because nothing will be substituted.
> The prior ${|| true} form was a parse error.
>
> Should ${{var}} be a "bad substitution", or print a warning about an
> empty command?  Otherwise it just substitutes $var.

Again, I think I prefer the approach of doing as the user says even if
it doesn't appear to make much sense - so just substitude $var. If that
produces an error, what about ${{var}$=CMD} where CMD is unset.

> What about ${{var};} or ${{var}{}} etc.?

And there's probably a further half-dozen ways we've not thought of.

> Or we could declare ${{REPLY}...} as NOT synonymous with ${|...} and
> localize REPLY only in the latter of those.  That might actually make
> more sense.

That definitely makes most sense to me.

> Among the reasons I listed for not doing this, I forgot to mention
> that subscripts are allowed and you can't localize a subscripted
> parameter.

That's a fair argument for not making the parameter local.

Subscripts could be useful for something like:

  print ${{a[i]} i=2}

If we want automatic local for the subscript then maybe ${{a[]} REPLY=2}

While ${{arr} ... } does return arrays, it doesn't appear to be possible
to force array output from ${| ... }
In mksh:
  print ${|REPLY=(one two)}
does just print "one".

But various forms like ${${|REPLY=(one two)}[1]} return just "n"

I have built zsh with your latest patch and have not found any issues
with any tests I've thrown at it.

Perhaps worth including in a test case is the following which does
break after running the echo.
  while :; do; echo ${|REPLY=x;break}; done

Oliver


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

* Re: Nofork ${{var}...} edge cases
  2024-03-27 18:57 Nofork ${{var}...} edge cases Bart Schaefer
  2024-03-27 22:22 ` Oliver Kiddle
@ 2024-03-28  0:29 ` Mikael Magnusson
  2024-03-28  1:12   ` Bart Schaefer
  1 sibling, 1 reply; 7+ messages in thread
From: Mikael Magnusson @ 2024-03-28  0:29 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list

On Wed, Mar 27, 2024 at 7:58 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> Just seeking opinions:
>
> Should ${{} true} (empty variable name) result in "bad substitution"?
> Otherwise it's all side-effects, because nothing will be substituted.
> The prior ${|| true} form was a parse error.
>
> Should ${{var}} be a "bad substitution", or print a warning about an
> empty command?  Otherwise it just substitutes $var.

Is a space no longer required after } (formerly ||) to trigger the
command substitution? I personally would like to get an error in this
case because missing a $ in nested substitutions is a fairly common
typo. Eg I meant ${${var}}. And if no space is required, does that
mean if you typo ${${foo}:-blabla} into ${{foo}:-blabla}, :-blabla is
suddenly executed as a command? If the space is actually still
required then I don't have any real complaints. I think it was clearer
at a glance that ${|foo| bing} was doing something different as
opposed to ${{foo} bing} but i suppose i don't feel that strongly
about it.

-- 
Mikael Magnusson


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

* Re: Nofork ${{var}...} edge cases
  2024-03-27 22:22 ` Oliver Kiddle
@ 2024-03-28  1:00   ` Bart Schaefer
  2024-03-28  1:21     ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2024-03-28  1:00 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: Zsh hackers list

On Wed, Mar 27, 2024 at 3:22 PM Oliver Kiddle <opk@zsh.org> wrote:
>
> > Or we could declare ${{REPLY}...} as NOT synonymous with ${|...} and
> > localize REPLY only in the latter of those.  That might actually make
> > more sense.
>
> That definitely makes most sense to me.

Hrm, unfortunately that gets a bit dicey, because ${ ... } relies on
having the magic local $REPLY as a place to stash the captured stdout
long enough for paramsubst() to reach the point of returning it.  So
it would be weird for only ${{var}...} to "unlocalize" REPLY.  Might
have to think about that a bit more.

> If we want automatic local for the subscript then maybe ${{a[]} REPLY=2}

I'm not following how that is meant to work.

> While ${{arr} ... } does return arrays, it doesn't appear to be possible
> to force array output from ${| ... }

Correct, the magic local REPLY is always a scalar.

> In mksh:
>   print ${|REPLY=(one two)}
> does just print "one".

The current dev zsh implementation stringifies the whole array:
% print ${| REPLY=(one two)}
one two

> Perhaps worth including in a test case is the following which does
> break after running the echo.
>   while :; do; echo ${|REPLY=x;break}; done

Indeed, good idea.


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

* Re: Nofork ${{var}...} edge cases
  2024-03-28  0:29 ` Mikael Magnusson
@ 2024-03-28  1:12   ` Bart Schaefer
  0 siblings, 0 replies; 7+ messages in thread
From: Bart Schaefer @ 2024-03-28  1:12 UTC (permalink / raw)
  To: Mikael Magnusson; +Cc: Zsh hackers list

On Wed, Mar 27, 2024 at 5:29 PM Mikael Magnusson <mikachu@gmail.com> wrote:
>
> > Should ${{var}} be a "bad substitution", or print a warning about an
> > empty command?  Otherwise it just substitutes $var.
>
> Is a space no longer required after } (formerly ||) to trigger the
> command substitution?

A space was never required, it was just a convention I always followed
when writing examples:
% echo ${|x|x=foo}
foo

mksh doesn't require a space in ${|REPLY=foo} either.

> I personally would like to get an error in this
> case because missing a $ in nested substitutions is a fairly common
> typo.

Yes, I was just musing about that possibility myself.

> Eg I meant ${${var}}. And if no space is required, does that
> mean if you typo ${${foo}:-blabla} into ${{foo}:-blabla}, :-blabla is
> suddenly executed as a command?

With the patch as submitted so far, yes.  But requiring a space there
should be easy, and a pretty reasonable requirement.


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

* Re: Nofork ${{var}...} edge cases
  2024-03-28  1:00   ` Bart Schaefer
@ 2024-03-28  1:21     ` Bart Schaefer
  2024-03-28  1:32       ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2024-03-28  1:21 UTC (permalink / raw)
  To: Zsh hackers list

On Wed, Mar 27, 2024 at 6:00 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Wed, Mar 27, 2024 at 3:22 PM Oliver Kiddle <opk@zsh.org> wrote:
> >
> > > Or we could declare ${{REPLY}...} as NOT synonymous with ${|...} and
> > > localize REPLY only in the latter of those.  That might actually make
> > > more sense.
>
> Hrm, unfortunately that gets a bit dicey, because ${ ... } relies on
> having the magic local $REPLY as a place to stash the captured stdout

Oh, no, it doesn't:  I confused myself because some the tests in D10 do so.


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

* Re: Nofork ${{var}...} edge cases
  2024-03-28  1:21     ` Bart Schaefer
@ 2024-03-28  1:32       ` Bart Schaefer
  0 siblings, 0 replies; 7+ messages in thread
From: Bart Schaefer @ 2024-03-28  1:32 UTC (permalink / raw)
  To: Zsh hackers list

On Wed, Mar 27, 2024 at 6:21 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> > Hrm, unfortunately that gets a bit dicey, because ${ ... } relies on
> > having the magic local $REPLY as a place to stash the captured stdout
>
> Oh, no, it doesn't:  I confused myself because some the tests in D10 do so.

Please ignore that.  Both the tests AND the implementation do this.  Ugh.


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

end of thread, other threads:[~2024-03-28  1:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-27 18:57 Nofork ${{var}...} edge cases Bart Schaefer
2024-03-27 22:22 ` Oliver Kiddle
2024-03-28  1:00   ` Bart Schaefer
2024-03-28  1:21     ` Bart Schaefer
2024-03-28  1:32       ` Bart Schaefer
2024-03-28  0:29 ` Mikael Magnusson
2024-03-28  1:12   ` Bart Schaefer

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).