zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Up-scope named references, vs. ksh
Date: Sat, 17 Feb 2024 19:26:07 -0800	[thread overview]
Message-ID: <CAH+w=7akb334QvsofyMLtc7_091bmP=omjAGOZSc8eH8FWuTqQ@mail.gmail.com> (raw)
In-Reply-To: <CAH+w=7ateaqX5azdifTaFpJT6sX-fVhnEazgeYYXSWtJY8EQTw@mail.gmail.com>

Re-establishing the original examples:

On Sat, Feb 10, 2024 at 11:00 PM Stephane Chazelas
<stephane@chazelas.org> wrote:
>
> $ ./Src/zsh -c 'function f { typeset -n ref=$1; typeset var=foo; ref=X; echo "$ref ${(!)ref} $var"; }; f var; echo "$var"'
> X var X
>
> Compare with ksh:
>
> $ ksh -c 'function f { typeset -n ref=$1; typeset var=foo; ref=X; echo "$ref ${!ref} $var"; }; f var; echo "$var"'
> X var foo
> X

On Sun, Feb 11, 2024 at 8:14 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> On Sun, Feb 11, 2024 at 1:00 AM Stephane Chazelas <stephane@chazelas.org> wrote:
> >
> > One difference with ksh93: if the target variable was not set at
> > the time of the "typeset -n ref=target", then when ref is
> > assigned it may end up refering to a local target
[...]
> > It can be worked around with a typeset -g $1 before the typeset -n var=$1
>
> Is that really sufficient? Might the -g not select the wrong scope if
> the string $1 was passed down a couple of layers?

Here's what I'm concerned about:

 A) Src/zsh -c 'function f { typeset -n ref; ref=$1; typeset var=foo;
ref=X; echo "$ref ${(!)ref} $var"; }; f var; echo "$var"'

Note the subtle difference of separating the declaration of "ref" from
assignment to it.  Then consider this variation:

 B) Src/zsh -c 'function f { typeset -n ref; typeset var=foo; ref=$1;
ref=X; echo "$ref ${(!)ref} $var"; }; f var; echo "$var"'

Now the assignment is after the declaration of the local. And finally:

C) Src/zsh -c 'function f { typeset var=foo; typeset -n ref=$1;
ref=X; echo "$ref ${(!)ref} $var"; }; f var; echo "$var"'

Now the declaration+assignment of the nameref is after the local.

At least for the versions I have installed on Ubuntu 20.04, and with
parens removed from (!) as appropriate,
 A) ksh prints "X var foo\nX"; mksh prints an error and does not
create a nameref; Src/zsh prints "X var X".
 B) ksh prints "X var X"; mksh prints an error and does not create a
nameref; Src/zsh prints "X var X".
 C) ksh prints "X var foo\nX"; mksh prints "X var X"; Src/zsh prints "X var X".

So in part C, ksh "knows" that $1 is not just a string but an object
that belongs to a surrounding scope.  That's not going to happen in
zsh for a long time, if ever.  It's interesting that it matters that
the assignment appears in the argument of "typeset" e.g. part C vs.
part B.

Incidentally if I change the delcaration to
 typeset -n ref=
then ksh crashes in parts A and B.  The behavior of mksh and Src/zsh
is unchanged.

Adding the "typeset -g $1" changes the outcome for zsh only for part
A, where it prints "X var foo\nX" as Stephane indicated.  (The other
shells don't support -g.)

Given that it's not possible to fix part C for zsh, and zsh agrees
with ksh on part B and with mksh on B and C, is it worth making an
effort to fix Stephane's original example along with part A ?

> Seems to me you
> have to avoid re-using a variable regardless, especially if you do
>
> typeset -n var=
>
> (create what I've been calling a "placeholder") and then assign to var
> in some nested scope.

I have not dived into what happens in ksh if the assignments in A and
B happen in a nested function call.

> This may particularly be true of the "for var in ..." special case for namerefs.

The potential for confusion here seems large.  If I do

 typeset -n up=$1
 typeset var=foo
 for up in $2 $3 $4 $5; do ...

what scope am I applying to each of the words in $2, $3, ... ?  (E.g.,
suppose $3 is "var" instead of $1.)  Does it change if I do

 typeset -n up

instead?  Should that act like part B where the declaration is
separate from the assignment?  What if I do

 for up in "$@"

there?  The ksh implementation seems both inconsistent and slightly magical.

Anyway, the way to "fix" this is to implicitly perform the "typeset
-g" when assigning to the nameref, and if that creates a new parameter
then mark it unset.  But that still may put the new parameter at
global scope rather than at the scope from which $1 was passed; the
expansion of $1 is just a string like any other scalar, and there's no
magic to change that.  It seems as though the more consistent behavior
is what zsh is already doing.  I'm unsure whether doing the implicit
typeset only in ksh emulation mode is worthwhile as it gets us only
partway there.

Adding the "typeset -g" changes the behavior of a large number of
tests in K01, too.

Thoughts?


  parent reply	other threads:[~2024-02-18  3:26 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-06  2:21 [PATCH 1/3]: Add named references Bart Schaefer
2023-02-08  3:45 ` Oliver Kiddle
2023-02-08  4:59   ` Bart Schaefer
2023-02-08 23:16     ` Bart Schaefer
2023-02-09  0:47     ` Oliver Kiddle
2023-02-09  2:01       ` Oliver Kiddle
2023-02-09  5:45         ` Bart Schaefer
2023-02-09  4:49       ` Bart Schaefer
2023-02-09 20:49         ` Oliver Kiddle
2023-02-09 23:07           ` Bart Schaefer
2023-02-11  3:04             ` Bart Schaefer
2023-02-11  3:55               ` Bart Schaefer
2023-02-11  5:36                 ` Speaking of dangerous referents Bart Schaefer
2023-02-12  8:00                   ` Oliver Kiddle
2023-02-12  8:34                     ` Bart Schaefer
2023-02-11  7:02               ` [PATCH 1/3]: Add named references Oliver Kiddle
2023-02-11  7:45                 ` Bart Schaefer
2023-02-11 23:43                   ` Bart Schaefer
2023-02-11 23:45                     ` Bart Schaefer
2023-02-12  7:38                     ` Oliver Kiddle
2024-02-11  7:00                   ` Stephane Chazelas
2024-02-11 16:14                     ` Bart Schaefer
2024-02-11 16:42                       ` Bart Schaefer
2024-02-18  3:26                       ` Bart Schaefer [this message]
2024-02-20 21:05                         ` Up-scope named references, vs. ksh Stephane Chazelas
2024-02-20 22:30                           ` Bart Schaefer
2024-02-21 20:12                             ` Stephane Chazelas
2024-02-29  5:16                               ` Bart Schaefer
2024-03-01 18:22                                 ` Stephane Chazelas
2024-03-01 20:34                                   ` Bart Schaefer
2024-03-02  7:29                                     ` Bart Schaefer
2024-03-02 23:55                                       ` [PATCH] "typeset -nu" (was Re: Up-scope named references, vs. ksh) Bart Schaefer
2024-03-01 23:28                                   ` Up-scope named references, vs. ksh Bart Schaefer
2024-03-03 13:44                                     ` Stephane Chazelas
2024-03-03 19:04                                       ` Bart Schaefer
2024-03-03 20:27                                         ` Stephane Chazelas
2024-03-03 22:58                                           ` Bart Schaefer
2024-03-04 19:59                                             ` Stephane Chazelas
2024-03-05  1:05                                             ` Oliver Kiddle
2024-03-05  2:53                                               ` Bart Schaefer
2024-03-05  5:43                                                 ` Mikael Magnusson
2024-03-05  6:30                                                   ` Stephane Chazelas
2024-03-06  5:04                                                     ` [PATCH] local vs. nameref scoping (was Re: Up-scope named references, vs. ksh) Bart Schaefer
2023-02-12  9:02             ` [PATCH 1/3]: Add named references Oliver Kiddle
2023-02-12 18:59               ` Bart Schaefer
2023-02-12 19:45                 ` PM_* flags in zsh.h (was Re: [PATCH 1/3]: Add named references) Bart Schaefer
2023-02-12 21:01                   ` Oliver Kiddle
2023-02-12 22:54                 ` [PATCH 1/3]: Add named references Oliver Kiddle

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAH+w=7akb334QvsofyMLtc7_091bmP=omjAGOZSc8eH8FWuTqQ@mail.gmail.com' \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).