zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: Up-scope named references, vs. ksh
Date: Tue, 20 Feb 2024 14:30:56 -0800	[thread overview]
Message-ID: <CAH+w=7bucofSovKLc0kJeMT3RcKUc8ydhFSaGQqMALvJ_0S21Q@mail.gmail.com> (raw)
In-Reply-To: <20240220210553.g6imt3op6zahz4pa@chazelas.org>

On Tue, Feb 20, 2024 at 1:05 PM Stephane Chazelas <stephane@chazelas.org> wrote:
>
> 2024-02-17 19:26:07 -0800, Bart Schaefer:
> [...]
> >  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 that the ksh93 man page mentions:
>
> ksh93> Note  that,  for this to work, the positional parameter must be
> ksh93> assigned directly to the nameref as part of the declaration command
> ksh93> [...]   For instance, typeset -n var; var=$1
> ksh93> won't cross that barrier

And yet, after replacing ksh2020 with Version AJM 93u+ 2012-08-01 (I
had already done this on a different workstation but had forgotten
about it on the one where I tested):

ksh -c 'function f { typeset -n ref; ref=$1; typeset var=foo;
ref=X; echo "$ref ${!ref} $var"; }; f var; echo "$var"'
X var foo
X

So it sure looks like the barrier was crossed in a case where the doc
stated it would not be.

With 93u+ "typeset -n ref=;" produces
  ksh[2]: f[1]: typeset: : invalid variable name
rather than crashing.

> Note that ksh93 is special in that it does static scoping.
>
> I suppose zsh's private variables are similar to that.

Sort of ... private variables are never accessible in another scope,
even with namerefs.

> [...]
> > 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 if we have to work around it by namespacing
> variables or use argv like in functions/regexp-replace, that
> defeats the purpose of those namerefs.

You don't have to use namespacing, you just have to be sure that
either the caller has declared the parameter that it wants referenced,
or that the called function does the "typeset -g $1" preliminary (and
follows the doc recommendation about doing the "typeset -n" early).
There's nothing really to be done about the other cases, and
particularly not about specifying the (dynamic) scope of the referent.

> The only remaining problem is when the refered variable
> is not set/declared.

It IS possible to make that "typeset -g" implicit, but that has other
potential effects such as creating an (unset) parameter in global
scope (triggering WARN_CREATE_GLOBAL?).  If the parameter already has
been declared in a calling function scope, then even with the -g, the
nameref will point to that one, even if it's more than one level up
the call chain.  Which ought to be what you expect from dynamic
scoping.

> Contrary to mksh or bash, it alread gets this right:

Yes, as soon as an existing parameter is found the nameref records
what scope contains that parameter and looks for it there when
(de)referenced.  The glitchy bit is when there is no existing
parameter from which to obtain a scope.  I'm reluctant to try to make
this too magical, which is why I lean toward asking function authors
to explicitly do the "typeset -g $1" when that's what they mean.
Could certainly add this to the doc.

Or maybe add an option to "typeset" to turn this on or off, though I'm
not sure the existing function call framework provides all the needed
info.

> > 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
>
> I find that special behaviour of "for" quite surprising.

So did I.  I await with gritted teeth the first time that Ray forgets
to declare his loop variable with a nameref of the same name in scope.

Mixing namerefs with dynamic scoping does have a number of potential gotchas.

> I wasn't aware ksh93 and bash did it as well.

If they didn't, I wouldn't have implemented it.

> Seems buggy in ksh93:

Not all that surprising given the potential confusions.

> $ mksh -c 'a=1 b=2; f() { typeset name; for name do typeset -n v=$name; echo "$name=$v"; done; }; f a b'
> a=1
> b=2
>
> Won't work for "f name".

There's probably a way to do it with "f name a b" + shift, but I'm not
going to work it out.

> I can see how it can still be difficult to do without
> namespacing. For instance having a function that does option
> processing à la print -v var would have to do:

zparseopts and/or a declared assoc can get you a long way in this sort
of example while minimizing the opportunity for clashes.


  reply	other threads:[~2024-02-20 22:31 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                       ` Up-scope named references, vs. ksh Bart Schaefer
2024-02-20 21:05                         ` Stephane Chazelas
2024-02-20 22:30                           ` Bart Schaefer [this message]
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=7bucofSovKLc0kJeMT3RcKUc8ydhFSaGQqMALvJ_0S21Q@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).