On 6/17/24 10:38 PM, Zachary Santer wrote:
Bash Version: 5.2 Patch Level: 26 Release Status: releaseDescription: It just occurred to me that I could take advantage of arithmetic evaluation being performed when a variable with the -i integer attribute is assigned a value to create a visual distinction between working with regular variables and variables representing integers, i.e.: local this_var="words words words" local var[index]="${this_var}" local -r -i BIT_FLAG=2#0100 local -i value=BIT_FLAG After doing this, var[index] will be set to "words words words" and value will be set to 4. Going a step further and passing integer arguments to functions as the name of the variable, rather than passing its value with a parameter expansion of that variable, we run into a problem. I would expect func1 () and func2 () below to be equivalent. However, we see that when setting a local variable with the integer attribute, using the name of a variable at calling scope with the same name, the local variable is always assigned the value 0, if I'm not using an arithmetic expansion. I wondered if the call to 'local' was already referencing the local variable that it was in the process of declaring, which I imagine would've been unset at the time. 'set -o nounset' didn't cause it to error out, though. Of course 'declare -i other=other' is a no-op, but it doesn't break. Repeat-By: $ cat integer-scope #!/usr/bin/env bash set -o nounset main () { printf 'foo :\n' declare -i foo=1 func1 foo func2 foo printf 'bar :\n' declare -i bar=2 func1 bar func2 bar printf '"${baz}" :\n' declare -i baz=3 func1 "${baz}" func2 "${baz}" printf 'other :\n' declare -i other=4 declare -i other=other declare -p other } func1 () { declare -i bar="${1}" declare -p bar } func2 () { declare -i bar="$(( ${1} ))" declare -p bar } main $ ./integer-scope foo : declare -i bar="1" declare -i bar="1"
`declare' is a builtin, so its arguments are expanded before it is called. In the first example, you get what is essentially declare -i bar; bar=foo (to make it clear that the variable is created with the specified attributes before it's assigned to). Since the integer attribute is set, foo is treated as an expression, the variable with that name in the nearest scope gets expanded, and you have bar=1. In the second, you have the same thing (foo is not a variable local to func2's scope), but with a different syntax for the arithmetic evaluation that doesn't rely on the assignment to do it implicitly, so it's declare -i bar; bar=1
bar : declare -i bar="0" declare -i bar="2"
Same thing. You have declare -i bar; bar=bar (the variable is created before being assigned to). Since bar is a local variable at the current scope and it's unset, when the assignment is performed, it has value 0, and that gets assigned. Again, in the second example, since the arithmetic expansion is performed first, before the local variable is created, you use the variable in the nearest scope and get essentially declare -i bar; bar=2
"${baz}" : declare -i bar="3" declare -i bar="3"
This is the same as the first example.
other : declare -i other="4"
In this example, main is creating a local variable and then using its value in the next assignment. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRU c...@case.edu http://tiswww.cwru.edu/~chet/
OpenPGP_signature.asc
Description: OpenPGP digital signature