diff --git a/lib/date.rb b/lib/date.rb index 37c7630..70e2b00 100644 --- a/lib/date.rb +++ b/lib/date.rb @@ -1002,15 +1002,26 @@ class Date class << self - def once(*ids) # :nodoc: - for id in ids - module_eval <<-"end;" - alias_method :__#{id.to_i}__, :#{id.to_s} - private :__#{id.to_i}__ - def #{id.to_s}(*args, &block) - (@__#{id.to_i}__ ||= [__#{id.to_i}__(*args, &block)])[0] - end - end; + def once(*meths) + meths.each do |meth| + # Alias + orig_meth = '__nonmemoized_' + meth.to_s + alias_method orig_meth, meth + + # Redefine + define_method(meth) do |*args| + # Get cache + @__memoization_cache ||= {} + @__memoization_cache[meth] ||= {} + + # Recalculate or fetch + cache = @__memoization_cache[meth] + if !cache.has_key?(args) + cache[args] = send(orig_meth, *args) + else + result = cache[args] + end + end end end @@ -1037,7 +1048,10 @@ class Date # # Using one of the factory methods such as Date::civil is # generally easier and safer. - def initialize(ajd=0, of=0, sg=ITALY) @ajd, @of, @sg = ajd, of, sg end + def initialize(ajd=0, of=0, sg=ITALY) + @ajd, @of, @sg = ajd, of, sg + @__memoization_cache = {} + end # Get the date as an Astronomical Julian Day Number. def ajd() @ajd end diff --git a/test/ruby/test_date.rb b/test/ruby/test_date.rb new file mode 100644 index 0000000..45cb184 --- /dev/null +++ b/test/ruby/test_date.rb @@ -0,0 +1,13 @@ +require 'test/unit' + +require 'date' + +class TestDate < Test::Unit::TestCase + + def test_freeze + foo = Date.new + foo.freeze + foo.year + end + +end