I was doing some testing with two factorial funtions:
def fact1(n)
if n == 0
1
else
n * fact1(n-1)
end
end
with this one, I can go up to fact1(1970) (or fact1(1191) with
’–enable-pthread’). After that, I get a “stack level too deep” error.
The second funtion, below, just adds explicit "return"s:
def fact2(n)
if n == 0
return 1
else
return n * fact2(n-1)
end
end
With this one, I can only go up to fact2(1376) (or up to fact2(841) with
’–enable-pthread’), getting the same error as above after that.
Why does an explicit ‘return’ or compiling ruby with --enable-pthreads
changes the behaviour?
Also, I’m really puzzled by this one: if I put the two functions on the same file, fact2(1377) (or fact2(842) with ‘–enable-pthread’) will
give the following error: “Bignum can’t be coerced into Fixnum” instead
of the “stack level too deep” one.
Why does an explicit 'return' or compiling ruby with --enable-pthreads
changes the behaviour?
Adding an explicit return, add a function call. This is why ruby detect
quickly the stack overflow. --enable-pthreads modify internally the calls,
and this explain also the difference.
Also, I'm really puzzled by this one: if I put the two functions on the
*same file*, fact2(1377) (or fact2(842) with '--enable-pthread') will
give the following error: "Bignum can't be coerced into Fixnum" instead
of the "stack level too deep" one.
When ruby try to convert to a Fixnum it do
begin
# try the conversion
rescue
raise "Bignum can't be coerced into Fixnum"
end
if it detect the stack overflow when it's in the begin..rescue it will
give the error "Bignum can't be coerced into Fixnum".
If it detect the stack overflow outside the begin...rescue it give 'stack
level too deep'
This is the same error, but ruby give 2 different messages (because it's
in a begin...rescue)