D
D
Dgeremmi2014-08-24 12:21:20
ruby
Dgeremmi, 2014-08-24 12:21:20

How does this tutorial example work?

I'm reading Flanagan's book, Matsumoto's "The Ruby Programming Language", and came across an example that I didn't quite understand. Here it is (the example demonstrates a function that does memoization )

module Functional
  def memoize
    cache = {} # Пустой кэш. lambda захватывает его в свое замкнутое
                    # пространство
    lambda {
      # Заметьте, что ключ хэша - это сплошной массив аргументов!
      unless cache.has_key?(args) # если результата для этих аргументов в кэше нет,  
       cache[args] = self[*args] 
     end
      cache[args]
    }
  end
end
# далее демонстрируется его использование
factorial = lambda {|x| return 1 if x==0; x*factorial[x-1]}.memoize

What this method is for is clear to me, but here are a few things that are not clear to me.
1. Why does lambda get an array inside the memoize method?
2. In the line cache[args] = self[*args] self is lambda {|x| return 1 if x==0; x*factorial[x-1]}?
3. Why is there an asterisk operator (array unpacking) in self[*args]?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
vsuhachev, 2014-08-24
@Dgeremmi

Your ruby ​​2.1.2 example worked after a little tweaking
It's not clear what you mean? The following happens in memoize:
- a cache variable
is created - a function object is created, which is a wrapper for the function object on which the memoize method is called. At the same time, the cache variable (closure) is available inside the wrapper - the
created wrapper is returned
Yes, self is what the wrapper is made over, and [] applied to the function object is an analogue of call. That is, calling a wrapper with *args parameters
To unpack the array (oddly enough). That is, args is an array containing the passed parameters, and the wrapped lambda takes a number. Accordingly, the array must be unpacked.
Working code, you can poke prints and see what's equal

class Proc #!!!!!!
  def memoize
    cache = {} # Пустой кэш. lambda захватывает его в свое замкнутое
                    # пространство
    lambda { |*args| #!!!!!
      # Заметьте, что ключ хэша - это сплошной массив аргументов!
      unless cache.has_key?(args) # если результата для этих аргументов в кэше нет,  
        cache[args] = self[*args] 
      end
      cache[args]
    }
  end
end
# далее демонстрируется его использование
factorial = lambda {|x| return 1 if x==0; x*factorial[x-1]}.memoize

puts factorial.call(5)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question