람다 표현을 언제 인용해야합니까?


30

Q : 만약에 이제까지, 그것은에 유용 때를 날카로운 인용 lambda, 그 어느 경우 경우, 우리는해야 하지 을 날카로운 인용 lambda?

사람들은 lambdas를 세 가지 방식으로 사용 합니다.

  1. 평원: (lambda (x) x)
  2. 인용 : '(lambda (x) x)
  3. 날카로운 인용 : #'(lambda (x) x)

이 SO 스레드 는 세 가지 유형에 대해 설명하고, 이 SO 스레드 는 인용하지 않는 이유 (NB : not -quote ) 를 설명하고 lambda, 이 SO 스레드 는 인용과 샤프 인용의 차이점을 설명합니다.

이제 익명 함수수동 노드 와 docstring 은 자체 인용 lambda이라는 것을 주목하십시오 lambda.

이 양식의 전화 (lambda ARGS DOCSTRING INTERACTIVE BODY)는 자체 인용입니다. 람다 식을 평가 한 결과는 식 자체입니다. 람다 식은 함수로 취급 될 수 있습니다 ...

그래서, 그 표시 (lambda (x) x)#'(lambda (x) x)동일하지만 '(lambda (x) x)(바이트 컴파일 할 때, 가장 중요한)이 아니다.

그것은 하나의 거의 싶지 않을 것 같다 인용lambda하지만,이 때, 어느 경우에, 우리가해야 나에게 불분명하거나 안, 날카로운 인용 :

  • 날카로운 따옴표는 lambda단순히 문체 선택 입니까 , 아니면 날카로운 따옴표가 실제로 유용한 상황이 있습니까?
  • 우리가 a를 뾰족하게 인용 해서는 안되는 상황이 있습니까 lambda, 즉 그렇게 할 때 코드의 의미가 바뀔까요?

답변:


28

옛날 옛적에 , 람다에 대한 날카로운 인용이 필요했지만 이제는 더 이상 그렇지 않습니다.

따라서 (lambda (x) x)와 # '(lambda (x) x)는 동일하지만'(lambda (x) x)는 (가장 중요하게는 바이트 컴파일시) 아닙니다.

예. 실제로 처음 두 개는 평가할 때 완전히 동일합니다. 링크 한 매뉴얼 페이지에 설명 된대로 :

다음 형식은 모두 동일합니다.

(lambda (x) (* x x)) 
(function (lambda (x) (* x x))) 
#'(lambda (x) (* x x))

20 년 전에 Emacs 버전을 지원하려는 것 외에는 람다를 정확하게 인용 할 이유가 없습니다.

그러지 마


주석으로 :

  • 따옴표 (와 ')를 하드 인용하면 차이가 발생하여 바이트 컴파일을 방지합니다. 나는 그것이 유용하지만 누가 아는 시나리오를 생각할 수 없다.

  • 백틱은 람다에 진정으로 유용한 유일한 인용이지만 어떤 이유로 어휘 바인딩을 사용하지 않는 경우에만 사용됩니다.


바이트 컴파일에 대한 인용의 효과를 설명하는 예제가 포함 된 매뉴얼 의 익명 함수 섹션에 링크를 추가하십시오 .
Constantine

@ 콘스탄틴 완료. 전화를 걸고있는 게으른 원인이있어 OP가 이미 연결했습니다.
Malabarba

어휘 바인딩과 백틱을 사용하지 않는 것에 대한 당신의 의미를 명확히 할 수 있습니까? 감사.
coredump

@coredump 동적 바인딩을 사용하면 람다 내에서 외부 변수에 액세스 할 수있는 유일한 방법은 변수가 포함 된 목록으로 람다를 수동으로 작성하는 것입니다. 역학은 그런 종류의 일에 좋습니다.
Malabarba

BTW, 나는 "한 번에 한 번"이 실제로 적용되지 않는다고 생각합니다. 개정 기록 에서이 주제를 조사했을 때, 내가 갈 수있는만큼을 다시 lambda추가하는 매크로로 정의 된 것을 발견했습니다 function. IOW 경우 #'어떤 점에서 필요로하고있다, 그것은이었다 매우 초기 개발 코드입니다. Emacs-18에는 아직 필요하지 않았습니다.
Stefan

5

이후는 lambda그것이 인용되지 않은 해석, 이맥스 리스프 추적의 최신 버전 (ANSI) CL의 공시되지 때 어떤 이해가되지 않습니다 (lambda...)으로 #'(lambda...). 두 표기법은 인용 된 구조를 제외하고 거의 동일합니다.

선호 여부 (lambda...)또는 #'(lambda...)순전히 스타일의 문제입니다. 어떤 사람들은 나체 형태를 선호하는데, 이는 구문상의 소음을 피하고 다른 사람들은 (나 자신을 포함하여) 인용 된 형태를 선호합니다.


이것은 elisp 매뉴얼과 모순된다 : "Emacs Lisp에서, 그러한 목록은 함수 객체로 평가되는 유효한 표현입니다."
djechlin

8
"1990 년 이후에 출시 된 버전"과 같은 "최근 버전";-)
Stefan

0

보고의 계정에 추가 역사의 비트를 추가하는 것입니다 번호 '(람다 ...) 역사적 유산을?

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=4290 는 다음을 제안합니다.

이맥스 22 출발하는 lambda형태가 함수로서 사용되는 경우에 관계없이 선행 여부, 바이트이다 컴파일 function또는 #'. 22 이전의 Emacs 버전에서는 명시 적으로 #' 또는 function양식을 바이트 컴파일하려는 경우 사용해야합니다 .

바이트 컴파일러에 대해서는 모르겠지만 적어도 1993 년까지 lambda매크로 자체가 (function (lambda ...))폼을 반환한다는 것을 알 수 있습니다.

https://www.iro.umontreal.ca/~monnier/hopl-4-emacs-lisp.pdf 는 또한 말합니다 :

흥미롭게도 (MacLisp와는 달리) lambdaEmacs-19의 개발 초기에 매크로로 추가 될 때까지 1991 년 경까지는 Elisp 언어의 기술에 포함되지 않았습니다. Emacs-18에서 익명 함수는 다음 형식의 인용 값으로 작성되었습니다.

'(lambda (..ARGS..) ..BODY..)

그동안 lambda매크로가 지금은 거의 30 년 동안 불필요한이 인용했다, 이러한 행위의 많은 경우는 여전히 몸의 바이트 컴파일을 방지하더라도, Elisp 코드에서 발생합니다. 어쨌든, 1993 년에 Lucid Emacs 19.8 은 MacLisp에서 #'...독자의 속기를 (function ...)가져 왔습니다. 이맥스는 그 다음 해에 어울렸다.


0

백틱 람다 식을 사용하는 실용적인 예를 제공하고 싶습니다. 어휘 바인딩 / 변수 섀도 잉에 관한 것입니다. 백틱 람다 식을 사용하고 쉼표로 변수를 참조하면 전역 값을 얻을 수 있습니다.

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
             (let ((my-variable "Random"))
               (message ,my-variable)))))

M-x [RET] eval-buffer "랜덤 올드"출력

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall (lambda()
             (let ((my-variable "Random"))
               (message my-variable)))))

M-x [RET] eval-buffer "임의"출력

전역 변수와 변수의 로컬 변수를 결합한 세 번째 예

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
              (let ((my-variable "Random"))
                (message my-variable)
                (message ,my-variable)))))

M-x [RET] eval-buffer "랜덤" "랜덤 올드"출력


@npostavs 그것은 내 예제와 맞지 않았지만 나쁜 연습을 피하기 위해 예제를 수정했습니다
cjohansson at

더 나은 것은, 여전히 확신하지는 않지만 내부 바인딩에 다른 이름을 선택하는 것보다 개선 된 것입니다.
npostavs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.