bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [BUG] Associative array initial reference name is made available in


From: Greg Wooledge
Subject: Re: [BUG] Associative array initial reference name is made available in another context
Date: Sun, 2 Jul 2023 10:20:32 -0400

On Sun, Jul 02, 2023 at 03:04:25PM +0200, Top Dawn wrote:
> >
> > What makes you think so? Variables are always visible in invoked
> > functions, unless you shadow them using local/declare/typeset.
> >
> 
> Thank you very much for this information, I didn't know invoked functions
> inherited their parent functions variables.
> I understand better now the use of declare -n "reference", to make a copy
> of the referenced variable.

I wouldn't call it a copy.  It's more like a symbolic link.  It's a
reference to another variable, by name instead of by memory location.

Given this function:

f1() {
    local v=in_f1
    declare -n nameref=v
    f2
}

"nameref" refers to "v" by name, so anything that tries to use "nameref"
will refer to "v" instead.  It will use the same name resolution rules
that are always used.

If we have f2 defined like this:

f2() {
    printf '%s\n' "$nameref"
}

Then f2 will try to resolve "nameref".  There isn't a local variable by
that name, so it will look in the caller's scope, and so on.  If we run
f1 at this point, we get "in_f1" as output.

Now, what if we define f2 like this:

f2() {
    local v=in_f2
    printf '%s\n' "$nameref"
}

Now, when we run f1, we get "in_f2" as output.  Why?  Bash resolves
"nameref" by searching for a variable by that name, first in f2's
local variables, then in the caller's local variables, then in the
caller's caller's, and so on up to the global scope, until it finds
a matching variable name, or concludes that there isn't one.

Bash resolves nameref as a name reference to "v".  So now it begins a
search for a variable named "v".  Once again, it uses the local variables
of f2 first, then the local variables of f1, and so on.

Since we have a local variable named "v" in f2, the resolution stops
there, and that's the one it uses.

unicorn:~$ f2() { local v=in_f2; printf '%s\n' "$nameref"; }
unicorn:~$ f1
in_f2

Bash does not offer a way to refer to an instance of a variable at a
given scope.  There is no way to say, inside of f1, that the nameref
should refer to f1's instance of v, and no other instance.  Likewise,
there is no way to say "I want you, the function I am calling, to return
a value inside this variable vvv, which is my variable, and whose name
I am providing to you as an argument" without the function potentially
choosing a different instance of vvv.

That's why it's so important to (try to) use function-specifically-named
variables any time namerefs are in the picture.

f1() {
    local _f1_v=in_f1
    local _f1_nameref=_f1_v
}

And so on.  Yes, it's ugly as sin, but it's the only reasonable way to
avoid disaster.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]