Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH 1/3]: Add named references

On Tue, Feb 7, 2023 at 7:45 PM Oliver Kiddle <opk@xxxxxxx> wrote:
> with a reference to associative array elements.
>   typeset -A assoc
>   typeset -n ref=assoc[other]
>   ref=val
> This does work if assoc is assigned an initial value.

This should work after patch 4/3 that I just sent.

% typeset -n ptr=foo
% typeset -A assoc
% typeset -n ref=assoc[other]
% ref=val
% typeset -p assoc
typeset -A assoc=( [other]=val )

> The error message from, e.g. `typeset -Z2 ref` is "can't change type
> of a named reference". However, this is normally an attempt to change
> the type of the target of a reference (-n is not specified). It works
> fine for a scalar. So perhaps the error message should complain about
> changing the type of [associative] array elements instead.

Hmm, yes, that message should be changed if possible.

> One ksh feature which this doesn't cover is the special behaviour in ksh
> that `typeset -n ref=$1` will use the calling function scope to resolve
> the target.

This should also work after patch 4/3.

% typeset outside=OUTSIDE
% () {
typeset -n ref=$1
print $ref
} outside

Or do I misunderstand?

> The positional parameters are special-cased which I
> find rather ugly.

There's nothing explaining this in "man ksh93", can you point me
somewhere?  Not that your description makes this sound particular

I think the positionals might actually be best handled by a new
special parameter.  Cogitation needed.

> You could overload -u or -U for indicating Tcl-like
> uplevel.

It'd be easier to overload "-i N" for this since it already populates
the "base" integer in Param.

> The trouble with uplevel is that a called function can't know
> how many levels up to specify if people are allowed to write wrappers.

if the current locallevel were visible (cf. new special) then something like
 typeset -i $((locallevel-1)) -n up=argv
could work.  I think the current implementation of argv breaks this, tho.

I'm still not entirely following what problem this solves.

> I think a better solution is to take some syntax that isn't a valid
> variable name. e.g typeset -n ref=\&1 Repeated use of an initial & would
> indicate where another level of scope should be ascended. Wrapper
> functions then don't need their own nameref and can just pass, e.g.
> \&var as the variable parameter.

You're going to have to write out an example, sorry.

> I can't see an actual conflict in permitting -r, making the reference
> readonly not the target variable.

I'm also thinking about that.  The only use-case would be to prevent
something from doing "typeset +n ref".

> > With respect to zsh/param/private parameters, it's presently
> > prohibited to have a "public" reference to a private parameter.  It
> > might be possible to change this if someone can think of a use case.
> To a user it would seem like a fairly arbitrary restriction.

What purpose does it serve?  How does it help to have two names for
the same thing, one of which is "hidden" and the other isn't?  The
only analogy I can think of would be having a writable name for a
read-only variable.

> Coming back to the uplevel question, for private to be more useful it'd
> be really great to be able to have a private reference to a private
> variable from the calling function scope. I'm not sure how easy that
> even is with the current implementation of private.

You presently can't make anything that's private visible down-scope.
If you mean you want a variable that is visible in exactly one nested
scope, I'm back to asking for the use case.

> > There is one glitch: if the reference is created before the parameter
> > is declared private, and the private local is NOT hiding something in
> > an outer scope, then the reference does not retroactively generate an
> > error and assignments to the reference are silent no-ops.
> Not sure I follow. Sounds like something that ought to be fixed.

In Test/V10private.ztst it's the test with
 F:See K01typeset.ztst up-reference part 5
 F:Here ptr1 finds private ptr2 by scope mismatch, assignment silently fails

> > I also removed "kz" from TYPESET_OPTSTR in zsh.h -- as far as I can
> > tell they should never have been there in the first place.
> typeset -fu is like autoload. I think it was intentional.

Except every letter in TYPESET_OPTSTR has to correspond to the PM_
flag at that same index position, and the PM_ flags matching the k and
z options are way out of sequence for that.

> Note that recent bash also has namerefs so should perhaps be compared.

The special behavior of namerefs in "for" loops and implementing
"unset -n" might be good; the latter isn't mentioned until the "unset"
builtin in the ksh93 doc so I missed it entirely.

> PS. The basic approach is much the same as that which was rejected many
> years back with consensus at that time being that a C pointer reference
> should be used.

And yet we implemented ${(P)...} which is actually a bit grottier.  I
did consider overloading pm->old but was leery of messing up locals so
decided to leave it as a future optimization.

> I did make a start at the time using reference counting

That was the other part that worried me ... everything just went
(relatively) smoothly if most of the code could continue pretending
namerefs were scalars.

> I think I also concluded that it
> wouldn't work for private variables because of their somewhat too clever
> implementation.

They could be a lot less clever if they could move into the main
shell.  Most of the cleverness was necessary for making them modular.

Messages sorted by: Reverse Date, Date, Thread, Author