Что такое "нисходящие фунарги"?
Джейми Zawinski использует этот термин в своих (1997) статья "java отстой" как будто вы должны знать, что это значит:
Я действительно ненавижу отсутствие нисходящих фунаргов; анонимные классы-Хромая замена. (Я могу жить без долгоживущих замыканий, но я нахожу отсутствие указателей функций огромной болью.)
похоже, это сленг Лиспера, и я мог бы найти следующее краткое определение здесь, но я почему-то думаю, я все еще не понимаю:
многие замыкания используются только в пределах Привязок, на которые они ссылаются; они известны как "нисходящие фунарги" на языке Lisp.
не Стив Yegge, Я бы просто чувствовал себя глупо сейчас, но, кажется, это может быть нормально, чтобы спросить:
Джейми Завински-герой. Живая легенда. [...]парень, который может использовать термин "нисходящие funargs" , а затем смотреть на вас, просто смея вас попроси его объяснить это, кретин.
--XEmacs мертв, да здравствует XEmacs
Так есть ли здесь Лиспер, который может скомпилировать это для программистов C-стиля, таких как я?
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