programing tip

"하향 funargs"는 무엇입니까?

itbloger 2020. 12. 30. 07:44
반응형

"하향 funargs"는 무엇입니까?


Jamie Zawinski 는 그의 (1997) 기사 "java sucks" 에서이 용어를 사용합니다 .

나는 하향식의 부족이 정말 싫다. 익명 클래스는 절름발이 대체물입니다. (저는 오래 지속되는 클로저없이 살 수 있지만 함수 포인터가 없다는 것은 큰 고통입니다.)

Lisper의 속어 인 것 같고 여기 에서 다음과 같은 간단한 정의를 찾을 수 있습니다 .하지만 어떻게 든 이해하지 못하는 것 같습니다.

많은 클로저는 그들이 참조하는 바인딩 범위 동안에 만 사용됩니다. 이들은 Lisp 용어로 "하향 funargs"로 알려져 있습니다.

Steve Yegge가 아니었다 면 지금은 어리석은 느낌이 들겠지만, 물어 보는 것은 괜찮은 것 같습니다.

Jamie Zawinski는 영웅입니다. 살아있는 전설. [...] "하향 funargs"라는 용어를 사용할 수있는 사람이 당신을 눈부시게하면서 그에게 설명을 요청하는 것뿐입니다.

- 이맥스는 죽은, 오래 살아있는 이맥스입니다

저 같은 C 스타일 프로그래머를 위해 이것을 컴파일 할 수있는 Lisper가 여기 있습니까?


하향 funarg는 반환되지 않거나 선언 범위를 벗어나는 지역 함수입니다. 현재 범위에서 다른 함수 로만 아래쪽 으로 전달할 수 있습니다 .

두 가지 예. 이것은 하향 funarg입니다.

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 해커가 일반적 으로 하향 funarg를 funarg 와 구별 할 수있는 이유 는 하향 funarg가 어휘 변수가없는 기존 Lisp에서 구현하기 쉽지만 일반적인 경우는 어렵 기 때문입니다.

전통적으로 로컬 변수는 가산함으로써 리스프 인터프리터 구현 결합 받는 (값 페어링 변수의 심볼 명 등) 환경 . 이러한 환경은 연관 목록을 사용하여 구현하기가 간단했습니다. 각 함수에는 고유 한 환경과 상위 함수의 환경에 대한 포인터가 있습니다. 변수 참조는 현재 환경을 조사하여 해결되었으며, 찾을 수없는 경우 상위 환경에서, 전역 환경에 도달 할 때까지 환경 스택에서 계속됩니다.

이러한 구현에서 지역 변수 는 동일한 이름의 전역 변수를 섀도 잉 합니다. 예를 들어, Emacs Lisp에서는 print-length목록을 축약하기 전에 인쇄 할 최대 길이를 지정하는 전역 변수입니다. 함수 호출 주변에이 변수를 바인딩하면 해당 함수 내에서 print 문의 동작을 변경할 수 있습니다.

(defun foo () (print '(1 2 3 4 5 6))); 출력은 인쇄 길이 값에 따라 다릅니다.

(foo); 인쇄 길이의 전역 값 사용
  ==> (12 34 5 6)

(let ((인쇄 길이 3)) (foo)); foo에 대한 호출 주위에 인쇄 길이를 로컬로 바인딩합니다.
  ==> (12 3 ...)

이러한 구현에서는 함수가 생성 될 때 함수의 환경에있는 변수가 평가 될 때 함수의 환경에 남아 있기 때문에 하향 funarg는 구현하기가 정말 쉽습니다.

이와 같이 작동하는 변수를 특수 또는 동적 변수 라고 하며 special선언을 사용하여 Common Lisp에서 만들 수 있습니다 .


Common Lisp에서 :

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

->  (4 5 6 7)

위의 형식에서 람다 함수는 DOWNWARD로 전달됩니다. 고차 함수 MAPCAR (함수와 값 목록을 인수로 가져온 다음 목록의 각 요소에 함수를 적용하고 결과 목록을 반환 함)에 의해 호출 될 때 람다 함수는 여전히 변수를 참조합니다. LET 표현식의 'a'. 그러나 그것은 모두 LET 표현 안에서 일어난다.

이 버전과 위의 비교 :

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

여기서 람다 함수는 LET에서 반환됩니다. 조금 위로. 그런 다음 MAPCAR로 전달됩니다. MAPCAR가 람다 함수를 호출하면 주변 LET가 더 이상 실행되지 않습니다. 여전히 함수는 LET에서 변수 'a'를 참조해야합니다.


Funarg 문제 라는 Wiki에 대한 꽤 설명적인 기사가 있습니다.

"하향 funarg는 함수가 실제로 실행되지 않을 때의 함수 상태를 참조 할 수도 있습니다. 그러나 정의에 따라 하향 funarg의 존재는이를 생성하는 함수의 실행에 포함되기 때문에 함수의 활성화 레코드입니다. 일반적으로 스택에 저장할 수 있습니다. "

참조 URL : https://stackoverflow.com/questions/581182/what-are-downward-funargs

반응형