Recursive functions in bash. Everyone seems to have the same advice: use local variables, stacks hacked together from bash arrays, or exitcodes. Ugh. Why not echo the result to standard output, like just about every other UNIX program?
ackermann() {
M=$1;N=$2
((M==0)) && echo $((N+1)) && return
((N==0)) && ackermann $((M-1)) 1 && return
ackermann $((M-1)) `ackermann $M $((N-1))`
}
This is somewhat contrived and more than a little inefficient. Not only that, but it's also incorrect: bash, like most "real" programming languages, suffers from integer overflow. Or does it?
function compute {
echo "$1" | bc | sed ':start /^.*$/N;s/\\\n//g; t start'
}
function ackermann {
M=$1;N=$2
((M==0)) && compute "${N}+1" && return
((M==1)) && compute "${N}+2" && return
((M==2)) && compute "2*${N}+3" && return
((M==3)) && compute "2^(${N}+3)-3" && return
((N==0)) && ackermann $((M-1)) 1 && return
ackermann $((M-1)) `ackermann $M $((N-1))`
}
Of course, most useful recursive bash scripts (like make!) don't abuse standard output in this horribly screw-brained way. Instead, they have side-effects (like compilation!) and reserve output for things like status or error messages. But that's not the point. The above snippets show that you can deal with recursion (and extended-precision arithmetic!) in bash in a relatively clean manner. (Some might object that, as a CS student, my definition of "relatively clean" is skewed. I'm declining comment on that one.)
(Then again:
./ackermann3.sh 4 3
Runtime error (func=(main), adr=19739): exponent too large in raise
I suppose there are limits to everything.)
January 27, 2009
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment