In an attempt to improve the bash-completion package we're trying to
improve the bash completion library functions by passing variables by
reference.  Passing variables by reference however, has a caveat in that
local variables override the passing by reference, e.g.:

    t() {
        local a
        eval $1=b
    }
    unset a; t a; echo $a  # Outputs nothing, expected "b"

I'm thinking of some workarounds below?

Workaround 1a: Show error

    t() {
        local a
        [[ $1 == a ]] && echo "ERROR: variable name conflicts"\
            "with local variable: $1"
        eval $1=b
    }
    unset a; t a  # Outputs error

Workaround 1b: Show error, automatically detecting local variables
        
    t() {
        local a
        local IFS=$'\n'; for var in $(local); do
            [[ $1 == ${var%=*} ]] && echo "ERROR: variable name"\
                "conflicts with local variable: $1"
        done
        eval $1=b
    }
    unset a; t a  # Outputs error


Workaround 2:  Create function wrapper, in order to reduce and obfuscate
local variables so that conflicts become less likely.

    # NOTE: Do not call this function directly, call 't()' instead
    _t() {
        local a b c d e  # Readable variables; no worry about conflicts
        eval $1=b
    }
    
    t() {
        local __1
        _t __1
        [[ $1 == __1 ]] && echo "ERROR: variable name conflicts \
            with local variable: $1"
        eval $1=\$__1
    }

Now we can call t() and receive an error if the variable causes a
conflict:

    $ t __1; echo $__1
    ERROR: variable name conflicts with local variable: __1

    $ t a; echo $a
    b


Thoughts?  Ideas?  Is there a bash-builtin to detect conflicts?  If not,
wouldn't it be an idea to add such a builtin?


Freddy Vulto
http://fvue.nl/wiki/Bash:_passing_variables_by_reference


Reply via email to