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.