M
Mark Ericson
In another thread someone mentioned tail recursion doesn't work right
in Ruby. Could someone please expand upon that?
in Ruby. Could someone please expand upon that?
In another thread someone mentioned tail recursion doesn't work right
in Ruby. Could someone please expand upon that?
e like implementing them in such a way that you get around the limitations =I wouldn't really call it optimization (although I guess it is), it's mor=
ction calls itself, which calls itself, for infinitly. Unfortunately, Ruby =Code like:
def fun(x)
fun(x)
end
fun(10)
should run forever, like it would in a language like Scheme or Lua. A fun=
he limits of hardware (the size of the stack). The "proper" way of implemen=It's not that Ruby doesn't work "right" in this case, it just runs into t=
d that way?By the way, is there a particular reason why tail calls aren't implemente=
I wouldn't really call it optimization (although I guess it is), it's
more like implementing them in such a way that you get around the
limitations of computer memory. (As opposed to just making them run
faster or something.) It doesn't really have anything to do with
efficiency in that sense.
Code like:
def fun(x)
fun(x)
end
fun(10)
should run forever, like it would in a language like Scheme or Lua. A
function calls itself, which calls itself, for infinitly. Unfortunately,
Ruby does not currently work that way.
It's not that Ruby doesn't work "right" in this case, it just runs into
the limits of hardware (the size of the stack). The "proper" way of
implementing tail calls would never use the stack, so it wouldn't be an
issue.
By the way, is there a particular reason why tail calls aren't
implemented that way?
-Justin
d that way?By the way, is there a particular reason why tail calls aren't implemente=
Well, what about this, for example?Collins said:I wouldn't really call it optimization (although I guess it is), it's more like implementing them in such a way that you get around the limitations of computer memory. (As opposed to just making them run faster or something.) It doesn't really have anything to do with efficiency in that sense.
more like implementing them in such a way that you get around the =Collins said:I wouldn't really call it optimization (although I guess it is), it's =
Well, what about this, for example?
Jakub said:Tail calls are essentialy safe GOTOs with argument passing, there is a
potential for performance gain. ;-) But in Ruby, its benefits wouldn't
be that noticeable, I guess...I kind of don't think that the programming
style that Ruby encourages is a good candidate for tail call
optimization. :-D
Neil said:Good point. Tail-call recursion is just a form of recursion that's easy
to turn into iteration, but (at least to me) one of ruby's strengths is
its iterators, so one might as well just write code in iterative form
instead of tail-call recursive form!
Yes, you are right - it can improve performance. What I meant was more that performance gains aren't usually the reason for doing it.
However, I am fairly sure it isn't that difficult (in the general case) to implement tail
calls this way. For example, in one of my classes we implemented a parser,
interpreter,stack,heap,etc. with proper tail calls.
Of course, it was for a tiny language, so that's why I'm not sure
about how easy it would be to do with Ruby.
The article you linked says at the end:
"Automatic optimization, on the other hand, is easy to implement in a compiler
and has little run-time cost. It will always identify opportunities for
tail recursion removal, even in complex functions. It improves execution
time without degrading the quality of source code, in some
cases by more than 700%, and can even beat carefully hand-optimized
code. Tail recursion removal frees the programmer to program
in the most elegant and natural style, without worrying about
performance problems resulting from inefficient language implementations."
Sounds like a good reason to implement it to me!
I do agree that Ruby doesn't encourage programming recursively, really, but why shouldn't it? Recursion isn't necessary, but it can allow for "nicer" solutions to naturally recursive problems.
BTW, I am not going to be upset if this isn't implemented in Ruby, I'm just saying it would nice
-Justin
Good point. Tail-call recursion is just a form of recursion that's easy
to turn into iteration, but (at least to me) one of ruby's strengths is
its iterators, so one might as well just write code in iterative form
instead of tail-call recursive form!
I found that ~1300 is the maximum depth of the stack on my machine....
So I can't use recursion to iterate over more than ~1300 items.
I hope people do realize that they can change the
maximum size of the stack allocated to their ruby process. For
example on Mac OS X using bash:
I hope people do realize that they can change the
maximum size of the stack allocated to their ruby process. For
example on Mac OS X using bash:
$ ulimit -s
8192
$ ruby -e '@i = 0; def foo; @i += 1; foo; end; begin; foo; rescue; puts
@i; end'
1204
$ ulimit -s 16384
$ ruby -e '@i = 0; def foo; @i += 1; foo; end; begin; foo; rescue; puts
@i; end'
2484
The ulimit command is built-in to the shell so if you are looking for
ways to change the maximum size of the stack for your processes, look
for ulimit or limit in your shell documentation.
I don't know enough about Windows to offer any hints for that environment.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.