As Craig said, it's clearer for the programmer and the ones that need to maintain it afterwards. Let the compiler figure out how to compile it in the most efficient way, and only optimize when it's indeed a verified bottleneck. In Knuth's words: "premature optimization is the root of all evil". (About optimization: often, using a better algorithm gains you more that tweaking a few bits here and there.)
So, go for the most understandable code.
As for the question whether it's too imperative, I would answer no. While the language allows you to modify those variables, you don't: you use them as constants. It's not because the language allows mutation, that your code is imperative. It's the code. (Which would've been my answer to the *ear-muffs* discussion a couple of days ago as well.)
A similar question is when using (nreverse) when returning a newly constructed list (common idiom in recursion with accumulators). It's not strictly functional, since you modify a variable. But for all practical purposes, it is functional (and it's also a bit of premature optimization :-) ).
So, adhere to the *ideas* of FP and avoid `extremism'. Else learn Haskell where even (random) is strict :-)
Cheers,
Peter.
Creating the local variables felt 'right' to me as well- but then I have 30 years experience of developing in Algol-family languages so I can't necessarily trust my instincts when writing Lisp code!