setq-local은 무엇을하고 언제 사용해야합니까?


16

SX에 대한 모든 문서와 많은 게시물을 읽은 후에도 버퍼 로컬 변수의 모든 변형에 대해 명확하지 않습니다.

내 이해에 대한 요약은 다음과 같습니다.

(defvar foo ..)파일의 동적 변수를 선언합니다. 그러나 변수는 (1) defvar 명령문 을 포함하지 않으면 다른 파일에 알려지지 않으며 (2) 변수는 버퍼 로컬이 아닌 범위 내에서 전역입니다.

(make-variable-buffer-local foo)defvar위 의 내용은 컴파일러와 다른 모든 사람들에게 변수 foo가 설정 될 때 설정된 모든 곳에서 버퍼 로컬로 처리된다는 것을 알려줍니다. 따라서이 패턴은 버퍼 로컬 변수를 선언하기에 좋은 스타일이며 두 명령문을 파일에 연속적으로 넣습니다.

(defvar xxx ...)                    ;declare xxx with global scope
(make-variable-buffer-local 'xxx)   ;but now make it buffer-local everywhere

편의상 (defvar-local xxx ...)위의 두 줄 대신 양식을 한 줄로 사용할 수 있습니다.

(defvar-local xxx ...)       ;make xxx buffer local everywhere

위와 같이 선언되면 변수 xxx는 setq 문의 다른 변수처럼 사용할 수 있습니다.

이미 전역 동적 변수 인 버퍼 로컬 변수의 단일 인스턴스를 원한다면 다음 선언을 사용합니다. 첫 번째는 전역 범위 동적 변수를 선언하고 두 번째 명령문은 현재 버퍼에서 해당 변수의 버퍼 로컬 버전 인스턴스를 하나만 만듭니다.

(defvar xxx ...)             ;declare xxx with global scope
(make-local-variable 'xxx)   ;make xxx local in this buffer only

이제 내 질문에 대한 질문 (위의 모든 내용은 이해가 올바른지에 대한 암시 적 질문이었습니다).

변수 값을 설정할 때 setq또는 을 사용할 수 있습니다 setq-local. 언제 사용해야 setq-local합니까? 왜?

setq-local버퍼 로컬 변수 또는 비 버퍼 로컬 변수를 사용하면 어떻게됩니까 ?

선언 된 변수 가 setq-local필요 defvar-local합니까?

setq-local정상에 defvar선언 된 변수 버퍼 로컬 변수로 돌려? (즉, setq-local어떻게 든 (make-variable-local xxx)선언 과 동등 합니까?


여분의 노동 Scott에게 감사합니다. 여기에서 여분의 역 따옴표를 넣겠습니다.
Kevin

2
(setq-local VAR VALUE)에 대한 속기이며 (set (make-local-variable VAR) VALUE)일반적인 관용구였습니다.
Drew

답변:


18

대부분의 가정은 가깝습니다. 나중에 몇 가지를 언급하겠습니다. 그러나 먼저 주요 질문입니다.

형식 setq-local은 단지 편의 일 뿐이며 make-local-variable뒤에 나오는 것과 동일 합니다 setq. 당신이했던 경우는 C-h f setq-local설명서를 참조하고이를 볼 수도 소스를 통해 클릭합니다. 이것이 첫 인상을 확인한 방법입니다. 코드는 make-local-variable실제로 변수 자체를 반환하는 것과 같은 것들을 최적화하고 있기 때문에 조금 모호 합니다. 를 사용하면 setq-local일부 코드에서 지역성을 가리킬 수 있으므로 전역 변수 값으로 코드를 재생할 수 없다는 것을 다른 사람들이 알 수 있습니다. 로컬 변수에 액세스하기 위해이를 사용할 필요 는 없습니다 . 모든 변수는 버퍼 로컬로 만들 수 있으며 변수에 닿는 모든 코드에 영향을 미칩니다 (글로벌 사본을 얻 setq-default거나 이와 유사한 것을 얻는 경우 제외 ).

이것이 기본 답변입니다. 자, 배경에는 약간 벗어난 것들이 있습니다. 당신이 그것에 대해 물었으므로, 나는 몇 가지를 다룰 것입니다.

첫 번째는 "다른 파일에 알려지지 않음"입니다. 이것은 사실이 아닙니다. 모든 코드는 포함하지 않고 (왜이 "글로벌"라고 있다고)이 전역 변수를 참조 할 수 있습니다 defvar(그리고 C-h f defvar그렇게 말한다). 실제로, 각 글로벌 변수마다 하나의 기본 defvar(docstring 및 기본값)이 있어야합니다. defvar변수 이름 만있는 A 를 사용하면 바이트 컴파일러 경고를 억제 할 수 있습니다. Emacs는 첫 번째 값과 docstring의 첫 번째 값만 사용합니다. defvar값 / docstring 이있는 여러 개가 있으면 코드를 읽는 사람들에게 혼란을 줄 수 있습니다. 그리고 파일 로딩 순서가 중요합니다.

일부 변수는 버퍼 로컬로만 사용 되도록 만들어 졌으며 사용되는 변수 입니다 defvar-local(또는 짧은 형식이 추가되기 전에 이전 코드에서 주로 사용 되는 두 부분 defvar/ make-variable-buffer-local). 이것은 모든 버퍼에서 버퍼 로컬로 만듭니다. 일부 변수의 경우 기본 사용은 버퍼 로컬이 아니지만 어떤 이유로 하나의 버퍼가 다른 값을 갖기를 원할 수 있습니다. 그때는 make-local-variable보통 일부 버퍼 설정 코드에서 거의 직후에 거의 사용하지 않습니다 defvar.

그리고 일반적으로 defvar양식 에는 두 가지 목적이 있습니다. 하나는 문서가 있어야 C-h v다른 사람들이 변수가 무엇인지 알 수 있습니다. 두 번째는 "default"값을 선언하여 변수가 항상 설정되도록하는 것입니다. 기본값 선언은 변수의 전역 (또는 기본) 인스턴스에만 영향을 미치며 해당 인스턴스가 아직 설정되지 않은 경우에만 사용됩니다. 즉, setq변수가 있고 파일을 defvar(예 :를 통해 require) 포함하면 defvar가 값을 변경하지 않습니다.

¹ 더 정확하게 defvar는 변수가 이미 설정된 경우 변수 값을 수정하지 않습니다 (단, 문서 문자열을 설정 함). 이는 (setq some-variable)패키지의 기본값을 무시하기 위해 패키지를로드하기 전에 사용자의 init 파일이 수행 할 수 있도록 하기위한 것입니다.


1
매우 명확한 답변에 감사드립니다. "다른 파일에 알려지지 않음"이라는 문구를 사용할 때 다른 변수들도 defvar를 추가하지 않으면 변수가 자유 롭다고 생각하기 때문에 자유 변수 경고를 생각하고있었습니다. 나는 set-local독자들에게 로컬 var가 설정되고 있음 을 알려주는 진술을 좋아한다 . 내 코드의 가독성을 향상시키기 위해 할 수있는 모든 것이 좋습니다! 추신. 소스를 클릭하여 더 자주 클릭하려고합니다. 내 현재 수준의 개발에서 종종 의미론을 얻지 못합니다 ... :-)
Kevin

1
" defvar각 글로벌 변수마다 하나만 있어야 합니다"는 엄격하지 않습니다 . 해당 VARNAME의 적절한 정의 (초기 값 및 이상적으로는 docstring)와 상관 (defvar VARNAME) 없이 값이 선언 되지 않은 상황 이 있습니다.
phils

2
있음을 유의하십시오 setq-localdefvar-local단지 이맥스 24.3에 소개되었다.
phils

1
@ phils, 당신이 말하는 상황을 식별 할 수 있습니까, 가치 없이(defvar varname) 선언 해야하는 곳 은 무엇입니까? 나는 내가 다른 곳에서 선언 한 전역 파일에 대한 변수 변수 경고를 제거하는 방법을 묻었을 때 Drew가 다른 스레드에서 제안한 것이라고 생각합니다. 나는 지금한다. 당신이 말하는 상황입니까?
Kevin

1
바이트 컴파일 경고를 피하는 것이 한 가지 이유입니다 (예 C-h i g (elisp) Warning Tips). 다른 하나는 어휘 바인딩을 사용하는 라이브러리를위한 것으로, 필요한 경우 변수가 어휘 바인딩되지 않고 동적으로 바인딩되도록합니다.
phils
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.