Головна сторінка Випадкова сторінка КАТЕГОРІЇ: АвтомобіліБіологіяБудівництвоВідпочинок і туризмГеографіяДім і садЕкологіяЕкономікаЕлектронікаІноземні мовиІнформатикаІншеІсторіяКультураЛітератураМатематикаМедицинаМеталлургіяМеханікаОсвітаОхорона праціПедагогікаПолітикаПравоПсихологіяРелігіяСоціологіяСпортФізикаФілософіяФінансиХімія |
Одинокого (проживаючого самотньо) громадянинаДата добавления: 2015-08-30; просмотров: 522
Функциональный аргумент можно пометить с помощью специальной, предотвращающей вычисления формы FUNCTION: (FUNCTION функция) В отличие от обычной блокировки вычислений с помощью QUOTE форму FUNCTION называют функциональной блокировкой. Функциональную блокировку можно записывать сокращенно: #’f Û (FUNCTION f) Если нужно передать функции данные в том виде, как они записаны, то используется обычная форма quote. Функции quote достаточно и для передачи имени функции или лямбда-выражения, если в нем не используются свободные переменные. Работа со свободными переменными оказывается более сложной, чем с параметрами, поскольку значения свободных переменных зависят от контекста вычислений. Сформированный на время вычисления функции вычислительный контекст после окончания ее вычисления пропадает, и на него невозможно позже сослаться или вернуться к нему. Для запоминания контекста вычисления в Лиспе используется замыкание (лексическое замыкание) – пара, состоящая из функции (лямбда-выражения) и контекста. Замыкание создается формой FUNCTION. В замыкание из контекста определения функции включаются лишь связи свободных переменных функции. Замыкание можно сохранять как любой лисповский объект, присваивая его какой-нибудь переменной: >(defun add(x) (function (lambda (y) (+ x y)))) ADD >(setq add3 (add 3)) ; x = 3 #<Closure SPECIAL::APPLY-INTERPRETED-CLOSURE ...> >(funcall add3 5) ; y = 5 Связи свободных переменных замыкания остаются в силе до следующего запуска замыкания, и этим переменным можно даже присваивать новые значения. Необходимость замыканий продемонстрируем на следующем примере. Допустим, Вы хотите написать программу, которая при вызове генерирует степени двойки. Это должно выглядеть следующим образом: >(power-of-2-generator) >(power-of-2-generator) >(power-of-2-generator) ... Один из способов написать такой генератор – использовать глобальные переменные: (defvar *previous-power* 1)
(defun power-of-2-generator () (setf *previous-power* (* 2 *previous-power*)))
Функция работает, но она использует глобальные переменные, а это значит, что мы не можем иметь больше одного power-of-2-generator генератора одновременно, так как глобальная переменная *previous power* может сохранять только одно значение. Можно ли обойтись без глобальных переменных? Для сохранения состояния генератора может быть использовано замыкание. Связи свободных переменных замыкания остаются в силе до следующего запуска замыкания. Этим переменным также можно присваивать значения. Используя замыкание, получим следующее определение генератора степеней двойки: (defun make-power-of-2-generator (previous-power) #'(lambda () (setf previous-power (* previous-power 2)))) Теперь мы можем создать несколько генераторов, так как каждый из них использует собственную переменную previous-power. >(setf g1 (make-power-of-2-generator 1)) #<Closure SPECIAL::APPLY-INTERPRETED-CLOSURE ...>
>(setf g2 (make-power-of-2-generator 10)) #<Closure SPECIAL::APPLY-INTERPRETED-CLOSURE ...> >(funcall g1) >(funcall g2) >(funcall g1) >(funcall g2) >(funcall g1)
|