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-local및 defvar-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.