Comments 16
Отличный подробный разбор, но не хватает одного из самых интересных примеров мемоизации - когда макрос подсчитывает количество выполнений функции и если оно превышает некоторый порог - компилирует её для улучшения производительности. Если хочется пример можно было бы сделать маленькую виртуальную машину с собственным байткодом чтобы проиллюстрировать это.
r) r))))))
Вот моё главное впечатление от Lisp'а. Некрасиво и очень, очень много скобок.
Зато позитивно))) С другой стороны соглашусь, код на лиспе для меня почти не читаем, взять любой менее экозотический язык, то код будет +/- понятен. Вспоминаю свою боль когда я пытался поправить скрипты для автокада, в итоге проще было поправить на чертеже.
У Норвига в PAIP сделано функциями. Там как-то проще, чем через макросы, в том смысле, что о просачивании символов в другую область видимости не надо заботиться.
(defun memo (fn name key test)
"Return a memo-function of fn"
(let ((table (make-hash-table :test test)))
(setf (get name 'memo) table)
#'(lambda (&rest args)
(let ((k (funcall key args)))
(multiple-value-bind (val found-p)
(gethash k table)
(if found-p
val
(setf (gethash k table) (apply fn args))))))))
(defun memoize (fn-name &key (key #'first) (test #'eql))
"Replace fn-name's global definition with a memoized version"
(setf (symbol-function fn-name)
(memo (symbol-function fn-name) fn-name key test)))
У макроса есть какое-то существенное преимущество?
Как я понимаю, getd
- это функция из HomeLisp'а, которая возвращает исходный код функции? В Common Lisp такого нет, вроде бы.
Да, у меня тоже была такая мысль.
и да - getd делает именно это. Но не я это придумал. В основе HomeLisp лежит книга С.С.Лаврова и Г.С.Силагадзе, там такая функция была (кажется)...
Спасибо, что добавили разъяснение в статью.
Так и не пойму, можно ли трюк Норвига с заменой `(symbol-function fn-name)` провернуть где-то кроме CL и основанных на нём вариантов. При наличии исходного текста функции макрос выглядит как более переносимое решение всё-таки, да. Хотя по сути это точно функция - отображение входного аргумента в возвращаемое значение.
Да, в Common Lisp такого нет, но очень легко сделать обернув defun макросом и определяя свои функции через него
Мемоизация в Лиспе