Skip to content

Commit

Permalink
remove the indirect expansion section
Browse files Browse the repository at this point in the history
  • Loading branch information
glennj committed Feb 21, 2025
1 parent 5076cac commit 943388a
Showing 1 changed file with 11 additions and 44 deletions.
55 changes: 11 additions & 44 deletions concepts/more-arrays/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ declare -p subarray # => subarray=([0]="three" [1]="four")
## Passing an Array to a Function

This is not as straightforward as other languages you might be know.
There are 3 techniques to pass an array to a function, and only one of them allows you to "mutate" the array that was passed.
There are two main techniques to pass an array to a function.

### Pass the Elements

In the first technique, you just pass the array's values and collect them into a local array in the function.
In the first technique, you pass all of the array's values and collect them into a local array in the function.

```bash
myfunc() {
Expand All @@ -105,59 +105,26 @@ array_original=(11 22 33 44)
myfunc "${array_original[@]}"
```

The function's array holds a copy of the values.
The function's array holds a _copy_ of the values.
Any changes made to the array in the function are not reflected in the outer scope.

### Pass the Array Name

For these two techniques, you pass the array _name_ as a string.

#### 1. Using Indirect Expansion

Suppose you have variable `x=5` and variable `y=x`, and you want to use the `y` variable to get the value `5`.
Some other languages let you do `$$y` but not Bash.
Bash has a technique called **indirect expansion** (described in the manual in [Shell Parameter Expansion][parameter-expansion]).
In bash, this uses the `!` character in a different way than we have seen before:

```bash
x=5
y=x
echo "the value is ${!y}"
```

We will use this technique to pass the array _name_ to the function, and indirectly access the values to make a copy them

```bash
myfunc() {
local array_name=$1
local temp="${array_name}[@]"
local array_copy=("${!temp}")
# do stuff with array_copy
declare -p array_copy
}

array_original=(11 22 33 44)
myfunc "array_original"
```

This technique is quite messy.
The `temp` variable will contain the _string_ `"array_original[@]"`.
Then the indirect expansion expands to the global array's values.

The function's array holds a copy of the values.
Any changes made to the array in the function are not reflected in the outer scope.

#### 2. Using a "nameref" Variable

This technique is more like the "pass by reference" capability you might be used to.
We will pass the array name to the function.
This technique is more like the "pass by reference" capability you might know from other languages.
You pass the array _name_ as a string.
The function will create a local variable with the "nameref" attribute.
This local array and the global array (whose name we passed in) are _the same array_.

```bash
myfunc() {
# note the `-n` option
local -n local_array=$1

# do stuff with local_array
for i in "${!local_array[@]}"; do
printf '%d => %s\n' "$i" "${local_array[i]}"
end

# we can mutate it
local_array+=(55 66 77)
}
Expand Down

0 comments on commit 943388a

Please sign in to comment.