Last active
August 29, 2015 14:17
-
-
Save tdg5/18e628bf987b2baf475a to your computer and use it in GitHub Desktop.
PoC of detecting tail call optimization by monitoring stack size via a lambda callback
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'tco_method' | |
module StackBuster | |
def self.fact_yielder(n, acc = 1, &block) | |
block.call(acc) | |
n <= 1 ? acc : fact_yielder(n - 1, n * acc, &block) | |
end | |
end | |
puts "StackBuster:" | |
StackBuster.fact_yielder(10) do |acc| | |
puts caller.length | |
end | |
module StackFloater | |
extend TCOMethod::Mixin | |
def self.fact_yielder(n, acc = 1, &block) | |
block.call(acc) | |
n <= 1 ? acc : fact_yielder(n - 1, n * acc, &block) | |
end | |
tco_module_method :fact_yielder | |
end | |
puts "\nStackFloater:" | |
StackFloater.fact_yielder(10) do |acc| | |
puts caller.length | |
end | |
# Output: | |
# ####### | |
# | |
# StackBuster: | |
# 3 | |
# 4 | |
# 5 | |
# 6 | |
# 7 | |
# 8 | |
# 9 | |
# 10 | |
# 11 | |
# 12 | |
# | |
# StackFloater: | |
# 3 | |
# 3 | |
# 3 | |
# 3 | |
# 3 | |
# 3 | |
# 3 | |
# 3 | |
# 3 | |
# 3 | |
## Or, alternately: | |
require "tco_method" | |
module FibYielder | |
def self.fib_yielder(index, back_one = 1, back_two = 0, &block) | |
yield back_two if index > 0 | |
index < 1 ? back_two : fib_yielder(index - 1, back_one + back_two, back_one, &block) | |
end | |
end | |
2.times do |idx| | |
initial_length = nil | |
is_tco = FibYielder.fib_yielder(10) do |fib| | |
if initial_length.nil? | |
initial_length = caller.length | |
else | |
break initial_length == caller.length | |
end | |
end | |
puts "Iteration #{idx + 1} is tco? : #{is_tco}" | |
next unless idx.zero? | |
FibYielder.extend(TCOMethod::Mixin) | |
FibYielder.tco_module_method(:fib_yielder) | |
end | |
# Iteration 1 is tco? : false | |
# Iteration 2 is tco? : true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment