Functions: Multiple Return Values
This is a technique that you’d fall back on, when you are really looking to get things more speedy. Arguably its not the prettiest coding technique, and fairly esoteric and I am not advocating to use it as the main interfacing technique. But it is useful, sometimes.
local
is not like your other programming language local variables
In bash a local
variable starts a scope at runtime for the function it
“lives” in and every function getting called from this function. This is in
stark contrast to compiled languages, where a local variable is only visible
inside the function itself.
Here is an experiment that shows this:
foo()
{
printf "%s\n" "${_bar}"
}
call_foo()
{
local _bar
_bar="hello"
foo
}
call_foo
printf "_bar is \"%s\"\n" "${_bar}"
_bar
is a local variable, not a global variable. The scope is limited to
the functions runtime scope, not what would be the compile scope. So the result
will be:
hello
_bar is ""
As a more compiler language oriented guy, I had to get over the hang-up, what a local variable is. It’s different the way a shell does it. There is no point in fighting the tool, instead make good use of it.
Multiple return values
I would never, ever (well just very rarely) use this feature to pass values into another function. There are named parameters for that. But for getting multiple return values out of a function, this can come in handy.
First of all its important to distinguish such multiple return values
from regular variables. I prefix them with an underscore _
.
Second a function should declare, what return values it will set.
This is done with a comment in front of the function detailing the local
declarations to be set by the caller.
Taking it all together this is how a multiple value function looks like in the called function:
#
# This function sets values of variables that should be declared
# in the caller!
#
# local _branch
# local _address
#
m_set_branch_address()
{
local mode="$1"
case "${mode}" in
whatever)
_branch="important"
_address=""
;;
*)
_branch=""
_address="unimportant"
;;
esac
}
and this is how the calling function does it:
print_branch_address_for_mode()
{
local mode="$1"
local _branch
local _address
m_set_branch_address "${mode}"
printf "address : %s\n" "${_address}"
printf "branch : %s\n" "${_branch}"
}
Again, it’s not beautiful, but it’s not too bad.
Note
I am toying with the idea of prefixing my multiple return value functions with
m_
but I haven’t done it yet.