Sujet : Re: About the "nameref" feature in bash...
De : janis_papanagnou+ng (at) *nospam* hotmail.com (Janis Papanagnou)
Groupes : comp.unix.shellDate : 08. Dec 2024, 14:57:25
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <vj48k5$3r1bq$1@dont-email.me>
References : 1
User-Agent : Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0
On 08.12.2024 13:51, Kenny McCormack wrote:
Bash has a "nameref" attribute on variables,
Is that a newer feature of bash? (My version doesn't support -n with
'local' or with 'declare'.) My response is based on the ksh feature.
The underlying ideas of the feature might be reflected in both shells
in similar ways.
that basically makes them like
"pointers" in languages like C. That is, the nameref variable has a value,
which is the name of another variable, and any/all references to the
nameref are, in fact, references to the other variable (with 2 exceptions
as discussed below). So, it works like this:
# Create a nameref variable and give it the value "foo"
declare -n MyNameRef=foo
foo=bar
echo $MyNameRef
(prints bar)
MyNameRef="Not bar"
echo $foo
(prints Not bar)
Yes.
Now, the docs present this feature as being primarily useful with
functions. That is, something like:
foo() {
local -n MyNameRef=$1
# Function manipulates MyNameRef, but is, in fact, manipulating
# the variable whose name was passed as an arg to the function.
}
Yes.
So, if we call foo as: foo bar
then references to MyNameRef inside foo() are, in fact, references to the
global variable "bar".
Yes.
This is all well and good, but it leaves open the question of "How do I
assign a value to the nameref itself, given that any reference to the
nameref gets converted to a reference to whatever the nameref points to?"
If used in functions - where the actual function parameter from the
call cannot be changed from within the function ex post - it makes
sense to not "overwrite" the calling parameter.
I consider it as a reference (or name?) parameter, so it makes (as I
perceive it) no sense to redeclare/re-use it as a local variable, or
reassign a new name to it. - To emphasize my point; it's more like
the '&' in C++'s function parameter declaration. - But, that said,
it's possible [in ksh] to reassign it by another parameter(-name),
like
function foo {
typeset -n nr=$1
typeset -n nr=$2
nr=42
}
(where 'typeset -n' is the ksh equivalent of bash's form). That code
might make sense if there's some conditional between the two typeset.
A loop like
one=1 two=2 three=3
typeset -n nr
for nr in one two three
do (( nr = --count ))
done
would affect the variables one, two, and three, respectively. (This is
documented for ksh namerefs.)
After the loop 'nr' still points to variable 'three' and an assignment
would affect that variable. Re-assigning 'nr' to a new variable name
requires [in ksh] to explicitly re-declare it, e.g.
typeset -n nr=zero
(now 'nr' being quasi an alias-name to the variable 'zero').
Maybe some ideas here may be conveyed to the bash's implementation and
its behavior.
Janis
The answer, as far as I can tell, is that there are exactly 2 exceptions to
the "always dereference" rule (for setting the value):
1) Use "declare" (or one of its synonyms, e.g., "local") to do the
assignment. This works, but is somewhat unappealing, since you may
end up declaring a variable more than once (which seems intuitively
wrong).
2) Use a "for" loop, like this:
for MyNameRef in one two three; do echo $MyNameRef; done
This magically assigns MyNameRef the values one, two, and three and
displays the values of those variables. Note that is different in
effect from the seemingly equivalent:
MyNameRef=one; echo $MyNameRef
MyNameRef=two; echo $MyNameRef
MyNameRef=three; echo $MyNameRef
Note: There is a syntax for reading the value of the nameref, but this
cannot be used to set the value. The syntax is: echo ${!MyNameRef}
In conclusion, my "reason for posting" is to confirm that I've got it right
that there are only 2 ways to set the value. Am I missing anything?