Skip to content

Instantly share code, notes, and snippets.

@behrends
Forked from anonymous/tail-recursive.rb
Created August 6, 2011 14:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save behrends/1129397 to your computer and use it in GitHub Desktop.
Save behrends/1129397 to your computer and use it in GitHub Desktop.
notes on Ruby Tail Call Optimization
# First, I suppose you have ruby 1.9.1 or 1.9.2
# Open irb. Execute this:
# RubyVM::InstructionSequence.compile_option = { tailcall_optimization: true, trace_instruction: false }
# Note, RubyVM::InstructionSequence.compile_option() doesn't have item :trace_instruction, still, you need to specify it. WTF?
# Also, it doesn't work if you just put it to the script. Don't know why yet. Tell me (@rofh) if you know.
# Then open the file:
# require "./tail-recursive"
# Then execute function:
# fact(30000)
# Unfortunately, this doesn't work:
#def fact(n)
# fact_tail = lambda { |x,acc| x == 0 ? acc : fact_tail.call(x - 1, x*acc) }
# fact_tail.call(n,1)
#end
# It is unfortunate, because ruby doesn't have support for nested functions ( as in Python )
# So we have to go with this:
def fact(n)
fact_tail(n,1)
end
def fact_tail(x,acc)
x == 0 ? acc : fact_tail(x - 1, x*acc)
end
# A simple wrapper to run your script with TCO support.
# Works on 1.9.1, doesn't work on 1.9.2 because of RubyVM::InstructionSequence.new format change, and there are no docs covering it. iseq.c isn't very informative for me as well.
#!/usr/bin/env ruby
filename = ARGV.first
iseq = RubyVM::InstructionSequence.new(open(filename).read,filename,1,tailcall_optimization: true, trace_instruction: false)
puts iseq.eval
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment