I want to implement a script foo.sh that culminates in the an execution of a command bar (with some arguments). The command bar modifies the current shell environment, which means that foo.sh must be sourced1. (BTW, the implementation of bar is entirely outside my control.)
The purpose of most of the code in foo.sh is to compute the arguments that will be passed to bar.
In order to keep foo.sh reasonably legible/maintainable, I find that I must define many auxiliary variables. Unfortunately, this sets the stage for
- namespace collisions (i.e. clobbering existing parameters)
- namespace pollution (i.e. cluttering the environment with superfluous parameters)
One possible way to avoid, or at least mitigate, these problems is to put most of foo.sh's code into a function (with all its variables declared as local) that echoes a suitable string of code to be eval'ed within the calling scope; e.g.
{
__messy_calculation () {
local x y z ...
local bar_arg_1 bar_arg_2 ...
...
echo "bar $bar_arg_1 bar_arg_2 ..."
}
eval "$( __messy_calculation )"
} always {
unfunction __messy_calculation
}
This takes care of the namespace pollution problem, and reduces the namespace collision problem to the one for the name of the function. (I'm not a big fan of using eval, though.)
I figure that this situation is generic enough that there already exist standard ways to address it. If so, please let me know.
1In case my reasoning here is flawed, let me just add that if I put all the code, including the call to bar, into a function, when I execute this function on the command line the current environment remains unaffected, which renders the function useless. In contrast, if I source the line that executes the call to bar, the current environment is modified as expected.
eval? Just call the function.__messy_calcuation;zshsupports anonymous functions:function { local x y z; local bar_arg_1 ...; ...; bar $bar_arg_1 $bar_arg_2; }