Quantcast
Channel: Pragmatic Forums | Posts by Bharat Ruparel
Viewing all articles
Browse latest Browse all 25

Example 9 from Episode 5 posted by Bharat Ruparel @ Fri, 27 Jun 2008 23:54:11 +0000

$
0
0

Hello Tony,
I am not sure what the answer is to your question because I cannot run the program with your module definition above. May be you have made more changes in the program below where remember method is called?

Please see my program below with your changes:



module Memoize
  def remember(method, &block)
    memory = {}
    define_method(method) do |*args|
      return memory[args] if memory.has_key?(args)
      memory[args] = block.call(*args)
    end    
  end
end      

class Discounter
  extend Memoize

  remember :discount do |*skus|
    expensive_discount_calculation(*skus)
  end                                       

  private

  def expensive_discount_calculation(*skus)
    puts "Expensive calculation for #{skus.inspect}" 
    skus.inject {|m,n| m + n }
  end
end

d = Discounter.new
puts d.discount(1,2,3)

puts d.discount(1,2,3)
puts d.discount(2,3,4)
puts d.discount(2,3,4)      

d1 = Discounter.new
puts d.discount(1,2,3)


I get the following error message:

C:/NBProjects/MetaProgDaveThomas/lib/main.rb:15: undefined method `expensive_discount_calculation’ for Discounter:Class (NoMethodError) from C:/NBProjects/MetaProgDaveThomas/lib/main.rb:6:in `call’ from C:/NBProjects/MetaProgDaveThomas/lib/main.rb:6:in `discount’ from C:/NBProjects/MetaProgDaveThomas/lib/main.rb:28

I am not sure what the answer is but from the error message, but it seems to me that the way you have defined the module the dynamic method discount becomes a class method when the module is extended in the class, and a class method cannot call an instance method expensive_discount_calculation.

Just after I wrote this post, I decided to check if my theory is true and made the following change to the definition/declaration of expensive_discount_calculation method.

def self.expensive_discount_calculation(*skus)

so, you see, the only change that I made is I put a self in front of the method name making it a class method. It ran fine. So the question boils down to what is better for meta-programming defining an instance method dynamically or a class method? At least in Java world when you don’t need to define and isolate state, i.e., instance variables, we prefer to define class methods since they are shared by all instances of the class and means less overhead for the compiler/interpreter, so I tend to think that this is preferable in terms of efficiency if the same logic holds true in Ruby world. But I am not an experienced Ruby and/or Rails programmer so I can easily be wrong.

I hope you don’t mind me joining the thread since these are precisely the kind of questions that I am struggling with at this point. It would be great to hear what David has to say.

Regards,

Bharat


Viewing all articles
Browse latest Browse all 25

Trending Articles