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

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

On Fri, Feb 10, 2023 at 11:02 PM Oliver Kiddle <opk@xxxxxxx> wrote:
> Bart Schaefer wrote:
> > On Thu, Feb 9, 2023 at 3:07 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> > >
> > > > Ksh prints "global reference cannot refer to local variable".
> I'd make it a fatal error unconditionally. I don't like it if the target
> of a nameref can switch to something else following a return.

Making it an unconditional error means that this sort of thing doesn't work:

typeset -n ref
() {
  typeset a=A b=B c=C
  for ref in a b c; do ref=${(L)ref}; done

> I'd be
> fine with the reference becoming unset at the time of the return if it
> refers to a variable that is going out of scope. Can that be done as
> part of the same code that drops the local variables?

Maybe.  Might look at that tomorrow.

> The mention of WARN_NESTED_VAR raises something else. Surely a reference
> should disable that warning:

Actually there's an argument that an unexpected up-reference is a
really good reason for that warning.  A function that intentionally
uses an up-reference could turn the option off locally.

> > > Relatedly, what should happen on any failed assignment?
> Current code even allows:
>   typeset -n ref
>   ref=ref

That's fixed in my sandbox.  Patch eventually forthcoming.

> I'd suggest that we need the self-reference check whenever assigning to
> a reference. But that entails evaluation of a subscript.

As I have it right now, self-reference checks do happen at any
assignment.  That's why I wonder if deleting the offending parameter
is OK.

Circular references hidden inside subscripts end up expanding to empty
string, as do command substitutions with the NO_EXEC trick.

> Do we to put recommended good practices in the doc at all as opposed to
> it being a terse description of the functionality. I'd prefer it out of
> the way with examples rather than adding fluff to the places you list.

The Functions chapter was rather too terse.  Here's what I've written to add:

--- 8< ---
Parameters declared by any of the 'typeset' family of commands during
the execution of a function become _local_ to the function unless the
'-g' option is used.  This is the _scope_ of the parameter, which
extends dynamically to any other functions called by the declaring
function.  In most cases, local parameters take the place of any other
parameter having the same name that was assigned or declared in an
earlier function scope.  (See *note Local Parameters::.)

A named parameter declared with the '-n' option to any of the 'typeset'
commands becomes a reference to a parameter in scope at the time of
assignment to the named reference, which may be at a different call
level than the declaring function.  For this reason, it is good practice
to declare a named reference as soon as the referent parameter is in
scope, and as early as possible in the function if the reference is to a
parameter in a calling scope.

A typical use of named references is to pass the name of the referent
as a positional parameter.  For example,

     pop() {
       local -n ref=$1
       local last=$ref[$#ref]
       print -r -- $last
     array=( a list of five values )
     pop array

prints the word values and shortens $array to '( a list of five )'.
There are no local parameters in pop at the time 'ref=$1' is assigned,
so 'ref' becomes a reference to 'array' in the caller.
--- >8 ---

> I'd also consider it bad practice not to always assign a reference when
> creating it.

That also doesn't work with the for-loop example above (even if the
nameref is moved inside the function).

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