Задать вопрос
@Dgeremmi

Как работает этот пример из учебника?

Читаю книжку Флэнагана, Мацумото "Язык программирования Ruby", столкнулся с примером, который я не совсем понял. Вот он (пример демонстрирует функцию, которая занимается мемоизацией)
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

То, для чего этот метод мне ясно, но вот несколько вопросов, которые мне не ясны.
1. Почему внутри метода memoize lambda получает массив?
2. В строке cache[args] = self[*args] self - это lambda {|x| return 1 if x==0; x*factorial[x-1]}?
3. Зачем в self[*args] стоит оператор-звездочка (распаковка массива)?
  • Вопрос задан
  • 2337 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 1
@vsuhachev
Ваш пример на ruby 2.1.2 заработал после небольшой доработки

1. Почему внутри метода memoize lambda получает массив?

Непонятно что вы имели ввиду? В memoize происходит следующее:
- создается переменная cache
- создается объект-функция, которая является оберткой для того объекта-функции на котором вызван метод memoize. При этом внутри обертки доступна переменная cache (замыкание)
- возвращается созданная обертка

2. В строке cache[args] = self[*args] self - это lambda {|x| return 1 if x==0; x*factorial[x-1]}?

Да, self это то над чем делается обертка, причем [] примененные к объекту-функции это аналог call. То есть вызов обертки с параметрами *args

3. Зачем в self[*args] стоит оператор-звездочка (распаковка массива)?

Для распаковки массива (как это ни странно). То есть args это массив содержащий переданные параметры, а оборачиваемая лямбда принимает число. Соответственно массив нужно распаковать.

Рабочий код, можете повтыкать принты и поглядеть что чему равно

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)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы