Подтвердить что ты не робот

Что такое "нисходящие лучи"?

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

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

Кажется, что это Lisper slang, и я нашел следующее краткое определение здесь, но почему-то я думаю, что до сих пор не получаю это:

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

Если бы не Steve Yegge, я бы сейчас просто почувствовал себя глупо, но, похоже, было бы нормально спросить:

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

- XEmacs мертв, долго жить XEmacs

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

4b9b3361

Ответ 1

Ненормальные 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;
}

Ответ 2

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

Причина, по которой старый хакер 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.

Ответ 3

В общем Lisp:

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

->  (4 5 6 7)

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

Сравните выше с этой версией:

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

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

Ответ 4

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

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