Что такое "нисходящие фунарги"?



Джейми Zawinski использует этот термин в своих (1997) статья "java отстой" как будто вы должны знать, что это значит:




Я действительно ненавижу отсутствие нисходящих фунаргов; анонимные классы-Хромая замена. (Я могу жить без долгоживущих замыканий, но я нахожу отсутствие указателей функций огромной болью.)




похоже, это сленг Лиспера, и я мог бы найти следующее краткое определение здесь, но я почему-то думаю, я все еще не понимаю:




многие замыкания используются только в пределах Привязок, на которые они ссылаются; они известны как "нисходящие фунарги" на языке Lisp.




не Стив Yegge, Я бы просто чувствовал себя глупо сейчас, но, кажется, это может быть нормально, чтобы спросить:




Джейми Завински-герой. Живая легенда. [...]парень, который может использовать термин "нисходящие funargs" , а затем смотреть на вас, просто смея вас попроси его объяснить это, кретин.



--XEmacs мертв, да здравствует XEmacs




Так есть ли здесь Лиспер, который может скомпилировать это для программистов C-стиля, таких как я?

697   4  

4 ответов:

нисходящие funargs-это локальные функции, которые не возвращаются или иным образом покидают область их объявления. Они только могут быть переданы вниз к другим функциям из текущей области.

два примера. Это нисходящий фунарг:

function () {
    var a = 42;
    var f = function () { return a + 1; }
    foo(f); // `foo` is a function declared somewhere else.
}

пока этого нет:

function () {
    var a = 42;
    var f = function () { return a + 1; }
    return f;
}

чтобы лучше понять, откуда взялся этот термин, вам нужно знать некоторую историю.

причина, по которой старый хакер Lisp может отличить вниз funargs от funargs в целом заключается в том, что нисходящие funargs легко реализовать в традиционном Lisp, в котором отсутствуют лексические переменные, тогда как общий случай сложен.

традиционно локальная переменная была реализована в интерпретаторе Lisp путем добавления обязательные (название символа переменная, в паре с ее значением) к окружающая среда. Такая среда была проста в реализации с использованием списка ассоциаций. Каждая функция имеет свою собственную среду и указатель на среду родительской функции. Ссылка на переменную была разрешена путем поиска в текущей среде, а если не найдена там, то в родительской среде и т. д. до тех пор, пока не будет достигнута глобальная среда.

В такой реализации, местные переменные тени глобальные переменные с тем же именем. Например, в Emacs Lisp,print-length - глобальная переменная, указывающая максимальную длину списка для печати перед его сокращением. Связывая эту переменную вокруг вызова функции, вы можете изменить поведение операторов печати внутри этой функции:

(defun foo () (print '(1 2 3 4 5 6))) ; output depends on the value of print-length

(foo) ; use global value of print-length
  ==>  (1 2 3 4 5 6)

(let ((print-length 3)) (foo)) ; bind print-length locally around the call to foo.
  ==>  (1 2 3 ...)

вы можете видеть, что в такой реализации, вниз funargs очень легко реализовать, потому что переменные, которые находятся в среда функции при ее создании будет по-прежнему находиться в среде функции при ее оценке.

переменные, которые действуют так, называются специальные или динамический переменные, и вы можете создать их в Common Lisp с помощью special декларации.

В Common Lisp:

(let ((a 3))
  (mapcar (lambda (b) (+ a b))
          (list 1 2 3 4)))

->  (4 5 6 7)

в приведенной выше форме лямбда-функция передается вниз. При вызове функции более высокого порядка MAPCAR (которая получает функцию и список значений в качестве аргументов, а затем применяет функцию к каждому элементу списка и возвращает список результатов), лямбда-функция по-прежнему ссылается на переменную 'a' из выражения LET. Но это происходит все в пределах выражения LET.

сравните выше с этим версия:

(mapcar (let ((a 3))
          (lambda (b) (+ a b)))
        (list 1 2 3 4))

здесь лямбда-функция возвращается из LET. Вверх немного. Затем он передается в MAPCAR. Когда MAPCAR вызывает лямбда-функцию, ее окружение LET больше не выполняется - по-прежнему функция должна ссылаться на переменную 'a' из LET.

есть довольно описательная статья на Вики под названием Funarg проблема

" a вниз funarg может также относиться к состояние функции, когда эта функция фактически не выполняется. Однако, потому что, по определению, существование нисходящего фунарга содержится в выполнение функции создает его, запись активации для функция обычно все еще может быть хранится в стеке."

Comments

    Ничего не найдено.