Alexander Klimetschek
Alexander Klimetschek

Reputation: 3714

How can I return a value from a function call in a shell script without creating a subshell?

I have a shell function, which accesses and touches a global array, which is basically a cache. It returns the value by echoing it:

declare -A cache

function get_value() {
    if [ ${cache[$1]+exists} ]; then
        echo ${cache[$1]}
    else
        value=$(create_value $1) # want to cache this result
        cache[$1]="${value}"
        echo $value
    fi
}

If I call it in the standard way

myValue=$( get_value "foo" )

it does not work because the cache[] update in the function happens in a subshell (the $( ... )) and is lost upon returning to the script aka parent shell.

The only thing I can think of is using a global variable (result) for the return value, but of course that's not so great in terms of structured programming:

declare -A cache

function get_value() {
    if [ ${cache[$1]+exists} ]; then
        result=${cache[$1]}
    else
        value=$(create_value $1) # want to cache this result
        cache[$1]="${value}"
        result=$value
    fi
}

get_value "foo"
myValue=$result

Is there a better alternative?

Using Bash 4.2.45.

Upvotes: 1

Views: 237

Answers (1)

Fred
Fred

Reputation: 6995

You can pass the variable name to which you want to assign the result as a parameter to the function, and use printf -v to perform the assignment :

declare -A cache

function get_value() {
    if [ ${cache[$1]+exists} ]; then
        printf -v "$2" "${cache[$1]}"
    else
        local value=$(create_value "$1") # want to cache this result
        cache[$1]="$value"
        printf -v "$2" "$value"
    fi
}

get_value "foo" my_value

If you are going to control variable scope, you might as well make your value variable local and, why not, make some kind of main() function to keep all variables local (even your cache).

Upvotes: 2

Related Questions