Skip to content

Instantly share code, notes, and snippets.

View tdg5's full-sized avatar

Danny Guinther tdg5

View GitHub Profile
@tdg5
tdg5 / stack_size_introspection.rb
Last active August 29, 2015 14:17
PoC of detecting tail call optimization by monitoring stack size via a lambda callback
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:"
@tdg5
tdg5 / factorials.rb
Created March 20, 2015 18:39
4 kinds of factorial
require "benchmark/ips"
def recursive_factorial(n)
n < 2 ? 1 : n * recursive_factorial(n - 1)
end
def tail_recursive_factorial(n, accumulator = 1)
n < 2 ? accumulator : tail_recursive_factorial(n - 1, n * accumulator)
end
@tdg5
tdg5 / itoa.rb
Last active August 29, 2015 14:17
itoa method
def itoa(int, base = 10)
str = ""
while int > 0
str = ((int % base) + 48).chr + str
int /= base
end
str
end
def itoarr(int, base = 10)
@tdg5
tdg5 / tco_ivar.rb
Created March 21, 2015 16:59
Instance variable reference from tail recursive call
require "tco_method"
class TCOInstance
extend TCOMethod::Mixin
attr_reader :tco_cycles
def initialize
@tco_cycles = 0
end
@tdg5
tdg5 / itr_pbt_deep_dup_build.rb
Last active August 29, 2015 14:17
iterative pbt_deep_dup_build
def self.pbt_deep_dup_build(clone, original)
mapped = Set.new
edges = [[clone, original]]
while edges.any?
builder, twin = edges.shift
pair_hash = "#{builder.class.name}:#{builder.hash}~#{twin.hash}".hash
next if mapped.include?(pair_hash)
mapped << pair_hash
pbt_dup_build(builder, twin)
@tdg5
tdg5 / partially_implemented_interface.rb
Created April 15, 2015 19:00
PartiallyImplementedInterface mixin
module PartiallyImplementedInterface
def self.not_implemented_error(klass, method)
raise NotImplementedError, not_implemented_message(klass, method), caller(2)
end
def self.not_implemented_message(klass, method_name)
"#{method_name} must be implemented by subclasses of #{klass.name}!"
end
private_class_method :not_implemented_message
@tdg5
tdg5 / pry_hooks.rb
Created June 9, 2015 23:16
Pry Hooks!
%w[
after_read
before_eval
after_eval
when_started
before_session
after_session
].each do |hook|
Pry.config.hooks.add_hook(hook.to_sym, "my_#{hook}_hook") do |_, _, _|
puts "hello from #{hook}"
@tdg5
tdg5 / better_oo_through_tco.rb
Last active September 30, 2015 12:34
Better Object-Oriented Design Through... Tail-Call Optimization?
# Abstract UnionList base class
class AbstractUnionList
private :initialize
def length
how_many?(0)
end
def how_many?(counter)
raise NotImplementedError
@tdg5
tdg5 / gc_friendly_tco.rb
Created October 7, 2015 12:55
Example demonstrating that tail-call optimization in MRI Ruby allows for earlier garbage collection of unreachable objects.
# Create some special classes to facilitate tracking allocated objects.
class TrackedArray < Array; end
class TrackedString < String; end
STRANG = "a" * 5000
# Other than a few extra escapes, the code below can be understood more or less
# as is. Any weirdness is to facilitate interpretting with/without tail-call
# optimization in a DRY manner.
KLASS = <<-CODE
class GcFriendlyTco
@tdg5
tdg5 / unary_ampersand_keeping_refs.rb
Last active October 7, 2015 14:19
Example seeming to demonstrate that unary ampersand operator holds on to obj references in Ruby 2.1.x
# Create some special classes to facilitate tracking allocated objects.
class TrackedArray < Array; end
class TrackedString < String; end
STRANG = "a" * 5000
class ClingyObjects
def generate(should_cling = false)
strs = TrackedArray.new
30000.times { strs << TrackedString.new(STRANG) }