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

Re: All the way up or current scope



Hm, that crept in during the recent round of changes.  It doesn't
behave that way in 5.0.9-test-2.

Indeed.

I hope you also saw my second reply where I propose a specification for -u that includes assignments and does, I think, exactly what we want for a -u ref. Notice that to implement this behavior, there is no need for the lookup scope that you had to add to Param instances to implement the current named references. Consider the fact that this could be generalized to all named references. What I mean is that it would be possible to completely get rid of the lookup scope and all the issues related with dangling references. Leaving a scope would be a no-op for named references because we would know that no named reference could ever point to a more deeply nested variable than itself.

Let me explain.

If the proposed specification for -u shown above is adopted, then a trivial addition is to add an optional integer argument to the -u option. With that, "typeref -n -u ref[=var]" would be equal to "typeref -n -u1 ref[=var]". In the specification "the enclosing scope" would be replaced with "the Nth enclosing scope" and in the implementation S-1 would be replaced with S-N. Trivial!

If the proposed -u specification is adopted, then I would very much like that we also allow this optional argument. It greatly enhances the power of named references. I can later explain if you wish.

Note that "typeref -n -u0 ref[=var]" also makes sense and I think it, too, should be allowed. This defines named references that are similar but not exactly the same as the named references currently defined with "typeref -n ref[=var]". If no nested scopes (relative to the typeref) are involved then they actually behave the same except for the following case:

function f() {
  typeref var=f;
  function g() {
    typeref -n ref=var;
    typeref -n -u0 refu0=var;
    echo "ref=$ref - refu0=$refu0";
    typeref var=g; # Arguably any sane programmer would put this before the two typeref -n above, then both would behave the same.
    echo "ref=$ref - refu0=$refu0";
  }
  g;
}

Output:
ref=f - refu0=f
ref=f - refu0=g

Note that the -u0 reference does NOT exhibit the stickiness of our current regular references. This is because it doesn't rely on extra lookup scope to remember where the variable matching the initialization value was, if any, when the reference was initialized. Actually, no lookup work at all is needed at initialization time. Since this case involves the definition of the same variable in two different scopes, it's a case that anyway won't work the same in ksh. And since implementing -u references is so much simpler than our current regular references, it begs the question whether it's worth having them.

An alternative is to say that "typeref -n ref=[var]" is equivalent to "typeref -n -u0 ref=[var]". The implementation would be very significantly simpler. Would it be more or less compatible with ksh? That, I don't know yet. My current guess is that for programs that could work the same in ksh and zsh if only named references worked the same both, our current named references and the proposed -u0 named references, would work the same. If that's indeed the case, then it really begs the question of whether the extra complexity of our current named references is warranted.

Philippe


On Mon, May 12, 2025 at 10:12 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
On Mon, May 12, 2025 at 9:19 AM Philippe Altherr
<philippe.altherr@xxxxxxxxx> wrote:
>
>> That's not how it currently works.  A parameter in the current scope
>> would be found only if the reference were first defined in a nested
>> scope to name a parameter that also existed in a (shallower) nested
>> scope, after which both of those nested scopes return.
>
> That's not true, currently (@1706805d4) a parameter in the local scope is also found even if there are no calls to nested scopes:
>
> () {
>   # scope with no parameters
>   () {
>     local -nu upref=$1
>     local var=at_upref
>     print -- $upref
>   } var
> }

Hm, that crept in during the recent round of changes.  It doesn't
behave that way in 5.0.9-test-2.

More later.


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