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

Re: Up-scope named references, vs. ksh



2024-03-03 14:58:04 -0800, Bart Schaefer:
[...]
> I've tried several different ways to explain this, so
> I'm just going to ignore this going forward.

Sorry for being so thick but I still don't get it. As there's
still a chance it's just we have different expectations, I'll
try a last attempt at clarifying mine below

[...]
> > Many if not most of the usages of
> > namerefs I've come across were to implement "read"-like commands
> > that return or can return something in a variable whose name is given by the
> > caller (and that can create the variable if needed).
> 
> There's nothing in the current implementation that prevents you from
> doing that if you choose your local names appropriately (and if
> nothing above you in the call chain hasn't already co-opted the name).

If we still have to namespace the names of the nameref variables
and any local variables of functions that use namerefs, then we
might as well do like in bash/mksh and just follow by name.

> > Where an approximation of what I'm suggesting is implemented in
> > zsh seems to work fine (with your patch applied).
> 
> But that approach doesn't work in the general case!  If you move
>   typeset value=$2
> to above the [[ -v $1 ]], then it either bombs, or assigns to the
> "wrong" $value.

To me,

typeset -n ref=var

should tie the ref to the var that is currently in scope at the
time ref is assigned var. If there's none in scope at the
moment, then it should be created unset and undeclared at the
global scope at that point, so that at the next ref=value, it's
that one that is set and not whatever variable with the same
name happened to appear at whatever scope that ref=value was
run.

In:

var=0
f() {
  local var=1
  nameref ref=var
  echo "$var"
}
f

I expect ref to poing to the local var and get "1" because
that's the var that was in scope at the time of ref=var

In:

var=0
f() {
  nameref ref=var
  local var=1
  echo "$var"
}
f

I expect 0.

In

f() {
  nameref ref=var
  local var=1
  echo "${var-unset}"
  ref=2
}
f
echo "$var"

I expect unset and 2
 
[...]
> > I really don't follow, dynamic scoping should make things easier
> > here.
> 
> Consider the case where your function is called 2 or more levels
> removed from the global scope.

In:

var=0
f1() {
  local var=1
  f2
}
f2() {
  f3
  local var=2
}
f3() {
  nameref ref=var
  echo "$ref"
}

I expect to see 1 as that's the var that is in scope at the time of ref=var.

> 
> > but having namerefs that can't create globals seems like a very
> > severe limitations to me
> 
> It's the same limitation as
> () {
>   local foo
>   unset foo
>   () { foo=bar }
> }
> which despite the appearance of the assignment in the nested function,
> doesn't create a global foo, it resurrects the caller's local foo.

Which is very much what I expect and agree it would be very wrong for that to
create a global foo.

> Ksh has static local scope (and an entirely different internal
> representation of parameters) so the local foo makes no difference to
> the nested function.

(unless the local foo is expected or the nest function uses
Bourne-style instead of Korn-style function definition) but yes,
I any case I agree with your description of how scoping would
work in ksh.

-- 
Stephane




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