Lambda method? Sample Mats code confuses me.

def memoize cache = {} lambda { |*args| unless cache.has_key?(args) cache[args] = self[*args] end cache [args] } end factorial = lambda {|x| return 1 if x== 0; x*factorial[x-1];}.memoize puts factorial.call 10 

Code from the book "Ruby Programming Language". But this confuses me: how is the (memoize) method applicable to lambda as its method? Can a lambda follow another lambda with a dot (.) As its own method?

 lambda {|x| return 1 if x== 0; x*factorial[x-1];}.memoize 

BTW: the above code works in irb, but the ruby ​​interpreter encounters an error as follows:

 memoize.rb:11: private method `memoize' called for #<Proc: 0x0000000103bba018@memoize.rb :11> (NoMethodError) 

Why?

+7
source share
2 answers

Where do you say this:

 def memoize #... end 

I think you want to say this:

 class Proc def memoize #... end end 

This will add the public memoize method for Procs and lambda { ... } (or -> { ... } in the new Rubies), giving you a copy of Proc.

Now on memoize . Methods return the value of their last expression, and for memoize , this is the last expression:

 lambda { |*args| unless cache.has_key?(args) cache[args] = self[*args] end cache [args] } 

So memoize returns a wrapper for Proc ( self ), which is a closure over cache , and this whole wrapper does the following:

  • See if cache entry for the argument list in question ( args array).
  • If we don’t have a cached value, then calculate the original Proc value ( self[*args] ) and save it in the cache.
  • Returns the cached value.

You can use the [] method to execute Proc, so proc.call(a, b) same as proc[a, b] .

+7
source

An object at the top level main , any method defined there, is added as a private instance method in Object (so that they are "accessible everywhere).

Why does it work inside an irb session? due to context mode (also here ), which is 3 by default in irb. For example, use the value 0 ( irb --context-mode 0 ), and now they will be added as private methods, as usual.

It would probably be preferable for pedagogical purposes if the fragment explicitly determined which class was changed, instead of using the implicit upper level.

+4
source

All Articles