Well, why do you think recursion is inefficient?
In Erlang's case it uses tail recursion (.Net IL can do this as well), which is actually slightly more efficient in terms of processing.
For example, with tail recursion, the CPU does something like this:
var first_list, second_list
label START_ITER:
if(first_list is empty)
goto FINISH
var first_elem = first_list[0]
var first_list.start_element = first_list[1]
second_list[n+1] first_elem
goto START_ITER
label FINISH:
return second_list
Whereas with a for loop, you get something like this:
var first_list, second_list
var i = 0
var limit = first_list.length
label START_ITER:
if(i == limit)
goto FINISH
second_list[n+i+1] = first_list[i]
i += 1
goto START_ITER
label FINISH:
// Done
The thing to note with the tail recursive example is that the list splitting just changes the node in the list that first_list points to. The for loop example uses more variable assignments to do much the same thing.
This also illustrates an important point with the differences between tail recursion (which is just a goto) and normal recursion, which will actually load up a function onto the stack. This just does not happen with tail recursion, and in erlang in general.
It's a close call, but there are some extra checks and additions in a for loop, so I can't recommend one over the other in terms of efficiency, but it terms of style, recursion has it down perfectly.
I believe it was best put as "To Iterate is Human, to recurse, divine"