Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Adds support for memoizing with arguments (keyword and normal).
  • Loading branch information
GeorgeErickson authored and David Dawson committed May 26, 2016
1 parent a88d40d commit 59f38dd
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 4 deletions.
9 changes: 5 additions & 4 deletions lib/memoist2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ def memoize(*method_names)
memoized_ivar = Memoist2.memoized_ivar_for(method_name)
memoized_module = Module.new do
module_eval <<-EVAL
def #{method_name}
unless #{memoized_ivar}
#{memoized_ivar} = [super]
def #{method_name}(*args)
#{memoized_ivar} ||= {}
unless #{memoized_ivar}[args]
#{memoized_ivar}[args] = [super(*args)]
end
#{memoized_ivar}[0]
#{memoized_ivar}[args][0]
end
def self.to_s
Expand Down
114 changes: 114 additions & 0 deletions spec/memoist2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def foo
count!
:bar
end

memoize :foo
end.new
end
Expand Down Expand Up @@ -85,6 +86,119 @@ def b

expect(subject.counter).to be 2
end

describe 'arguments' do
subject do
Class.new(Counter) do
include Memoist2

def foo(a)
count!
a
end

def foo_default(a = :bar)
count!
a
end

def foo_combo(a, b = :bar, *args)
count!
[a, b, args]
end

def foo_keyword(a: :bar, b: :bar)
count!
[a, b]
end

memoize :foo, :foo_default, :foo_combo, :foo_keyword
end.new
end

it 'memoizes arguments correctly' do
[1, 2, 3].each do |arg|
expect do
5.times { subject.foo(arg).should == arg }
end.to change{ subject.counter }.by(1)
end
end

it 'memoizes default arguments correctly' do
# No argument
expect do
5.times { subject.foo_default.should == :bar }
end.to change{ subject.counter }.by(1)

# Argument set to default
expect do
5.times { subject.foo_default(:bar).should == :bar }
end.to change{ subject.counter }.by(1)

# Argument given
[1, 2, 3].each do |arg|
expect do
5.times { subject.foo_default(arg).should == arg }
end.to change{ subject.counter }.by(1)
end
end

it 'handles a mixed case' do
[1, 2, 3].each do |arg|
expect do
5.times { subject.foo_combo(arg).should == [arg, :bar, []] }
end.to change{ subject.counter }.by(1)
end

[1, 2, 3].each do |arg|
expect do
5.times { subject.foo_combo(arg, arg).should == [arg, arg, []] }
end.to change{ subject.counter }.by(1)
end

[1, 2, 3].each do |arg|
expect do
5.times { subject.foo_combo(arg, arg, arg, arg * 2).should == [arg, arg, [arg, arg * 2]] }
end.to change{ subject.counter }.by(1)
end
end

it 'handles keyword arguments' do
expect do
5.times { subject.foo_keyword.should == [:bar, :bar] }
end.to change{ subject.counter }.by(1)

[1, 2, 3].each do |arg|
expect do
5.times { subject.foo_keyword(b: arg).should == [:bar, arg] }
end.to change{ subject.counter }.by(1)
end

[1, 2, 3].each do |arg|
expect do
5.times { subject.foo_keyword(a: arg*2, b: arg).should == [arg*2, arg] }
end.to change{ subject.counter }.by(1)
end
end
end



# it 'memoizes default arguments correctly' do
# [1, 2, 3].each do |arg|
# expect do
# 5.times { subject.default_arg(arg).should == arg }
# end.to change{ subject.counter }.by(1)
# end
# end

# it 'memoizes keyword arguments correctly' do
# [1, 2, 3].each do |arg|
# expect do
# 5.times { subject.keyword_arg(a: arg).should == arg }
# end.to change{ subject.counter }.by(1)
# end
# end
end

describe "class methods" do
Expand Down

0 comments on commit 59f38dd

Please sign in to comment.