bash function cannot change the value of a local variable when called by $()

That's because the command substitution, $(), spawns a subshell and the command inside runs in that subshell.

So any modifications made to any data structure would not be propagated to the parent shell. In other words, the changes are being made all right but in a subshell, hence the parent shell's relevant parameters are not being affected.

As a side note, when you execute a script, it runs in a subshell; A common trick to make all the changes of the parameters to be available in the calling shell is to source (.) the script.

Example:

$ foo() { bar=2 ;}

$ bar=1

$ $(foo)

$ echo "$bar"
1

$ foo

$ echo "$bar"
2