>> Except that it forks a subshell and consumes trailing newlines, and
>> the whole point of this exercise is to avoid forks and spurious
>> corruption of trailing newlines.
>
> I will try to find an alternative to eval $( )
The code below allows the callee to return any kind of values (including
arrays).
It preserves newlines. This code does not try to hack some half-baked
namespaces.
The optimized, "coproc" variant does not fork.
> Anything repetitive, done often enough, is observable even in an
> interactive environment. The bash-completion library of functions does
> a _lot_ of repetitive work, and we're talking about some of the core
> functions used within that library, possibly even hundreds of times over
> the course of a single tab-completion event.
Then maybe it's time to consider a non-shell implementation. Could
some Bash plugin implement the critical path in C?
blackbox1()
{
local a="some private var"
printf "$1=%s;" "foo"
printf "$2=%s;" '( some array )'
printf "$3=%s;" "'string with embedded
new lines
'"
}
blackbox2()
{
local a="some other private var"
printf "$1=%s;" "bar"
}
# BUG: with bash 4.0.35, repeatedly running this function *too fast*
# might error in "Too many open files"
forkingMain()
{
# Sourcing is safe because we trust our own blackbox functions
source <(blackbox1 a b c)
echo "--- blackbox1 returned:"; declare -p a b c
source <(blackbox2 a)
echo "--- blackbox2 returned:"; declare -p a
}
# Re-uses the same coproc subprocess to avoid forking
coprocMain()
{
local returnedDefs
echo 'blackbox1 a b c' >&${COPROC[1]}
read -r -d $'\0' -u ${COPROC[0]} returnedDefs
eval "$returnedDefs"
echo "--- blackbox1 returned:"; declare -p a b c
echo 'blackbox2 a' >&${COPROC[1]}
read -r -d $'\0' -u ${COPROC[0]} returnedDefs
eval "$returnedDefs"
echo "--- blackbox2 returned:"; declare -p a
}
forkingMain
coproc { while read; do $REPLY; printf '\x00'; done; }
coprocMain