범위(컴퓨터 사이언스)
Scope (computer science)컴퓨터 프로그래밍에서 이름 바인딩의 범위(변수 등의 엔티티에 대한 이름 관련성)는 이름 바인딩이 유효한 프로그램의 일부이며, 여기서 이름을 사용하여 엔티티를 나타낼 수 있습니다.프로그램의 다른 부분에서는 이름이 다른 엔티티를 나타낼 수도 있고(다른 바인딩이 있을 수도 있음), 또는 아예 아무것도 나타낼 수도 없습니다(제본되지 않을 수도 있음).스코프는 이름의 충돌을 방지하는 데 도움이 됩니다.이것에 의해, 이름에 다른 스코프가 있는 한, 같은 이름이 다른 오브젝트를 참조할 수 있습니다.이름 바인딩의 범위는 엔티티의 가시성이라고도 하며, 특히 더 오래된 기술 문헌에서는 참조 이름이 아닌 참조 엔티티의 관점에서 볼 수 있습니다.
또한 "scope"라는 용어는 프로그램의 일부 또는 프로그램의 특정 지점에서 유효한 모든 이름 바인딩 집합을 가리키기 위해 사용되며, 이는 더 정확하게 컨텍스트 또는 [a]환경이라고 불립니다.
엄밀하게[b] 말해 대부분의 프로그래밍 언어에서 "프로그램의 일부"는 소스 코드(텍스트 영역)의 일부를 가리키며, 어휘 범위로 알려져 있습니다.그러나 일부 언어에서 "프로그램의 일부"는 실행 시간(실행 중 시간)의 일부를 나타내며 동적 범위로 알려져 있습니다.이 두 용어 모두 다소 오해의 소지가 있어 정의에서 논의한 바와 같이 기술 용어를 오용하지만, 그 구별 자체는 정확하고 정확하며 각 용어의 표준 용어입니다.어휘적 범위는 이 기사의 주요 초점이며, 동적 범위는 어휘적 범위와 대조되어 이해된다.
대부분의 경우, 어휘적 범위에 기초한 이름 해결은 비교적 쉽게 사용하고 구현할 수 있는데, 이는 소스 코드에서 이름을 거꾸로 읽어 어느 엔티티를 참조하는지 결정할 수 있기 때문이다.또한 실행 시 프로그램을 컴파일 또는 해석할 때 이름과 컨텍스트의 목록을 유지할 수 있기 때문이다.이름 마스킹, 전진 선언 및 호이스트에서 어려움이 발생하는 반면, 특히 폐쇄에서 상당히 미묘한 문제가 발생한다.
정의.
이름(식별자)의 "범위"에 대한 엄격한 정의는 명확합니다. 어휘 범위는 "이름과 엔티티의 바인딩이 적용되는 소스 코드 부분"입니다.이는 1960년 ALGOL 60 규격의 정의와 사실상 동일하다.대표적인 언어 사양은 다음과 같습니다.
- ALGOL 60(1960)[1]
- 단순 변수, 배열, 라벨, 스위치 및 프로시저 등의 수량이 구별됩니다.수량의 범위는 해당 수량과 관련된 식별자 선언이 유효한 문과 식 집합입니다.
- C(2007)[2]
- 식별자는 객체, 함수, 태그 또는 구조체, 결합 또는 열거의 멤버, 유형 정의 이름, 라벨 이름, 매크로 이름 또는 매크로 매개 변수를 나타낼 수 있습니다.동일한 식별자는 프로그램의 다른 지점에 있는 다른 엔티티를 나타낼 수 있습니다.[...] 식별자가 지정하는 각 엔티티에 대해 식별자는 범위라고 불리는 프로그램텍스트 영역 내에서만 표시됩니다(즉, 사용할 수 있습니다).
- Go (2013년)[3]
- 선언은 공백이 아닌 식별자를 상수, 유형, 변수, 함수, 레이블 또는 패키지에 바인딩합니다. [...] 선언된 식별자의 범위는 지정된 상수, 유형, 변수, 함수, 레이블 또는 패키지를 나타내는 원본 텍스트 범위입니다.
일반적으로 "범위"는 선언이 유효할 때 특정 이름이 특정 변수를 참조할 수 있지만 함수, 유형, 클래스, 레이블, 상수 및 열거와 같은 다른 엔티티에도 적용할 수 있는 경우를 말합니다.
어휘 범위와 동적 범위
범위의 근본적인 차이는 "프로그램의 일부"의 의미입니다.어휘 범위(스태틱 범위라고도 함)가 있는 언어에서는 이름 해결은 소스 코드 내의 위치 및 명명된 변수 또는 함수가 정의된 위치에 따라 정의되는 어휘 컨텍스트(스태틱 컨텍스트라고도 함)에 따라 달라집니다.이와는 대조적으로 동적 범위를 가진 언어에서는 이름 해결은 실행 컨텍스트(런타임 컨텍스트, 호출 컨텍스트 또는 동적 컨텍스트라고도 함)에 의해 결정되는 이름이 발견되었을 때 프로그램 상태에 따라 달라집니다.실제로 어휘 범위에서는 로컬 어휘 컨텍스트를 검색하여 이름을 해결합니다.그것이 실패하면 외부 어휘 컨텍스트를 검색하여 이름을 해결합니다.반면 동적 범위에서는 로컬 실행 컨텍스트를 검색하여 이름이 해결되며, 실패하면 외부 실행 컨텍스트를 검색하여 콜을 진행시킵니다.압정을 [4]하다
동적 스코프는 일부 언어(특히 리스프 방언, 스크립트 언어, 템플릿 언어 등)에서 사용되지만, 대부분의 현대 언어는 변수와 함수에 어휘적 스코프를 사용합니다.[c] Perl 5는 어휘 범위와 동적 범위를 모두 제공합니다.어휘 범위 언어에서도 폐쇄의 범위는 폐쇄가 호출되는 위치가 아니라 폐쇄가 정의된 어휘 맥락에 따라 달라지기 때문에 미개시자에게 [citation needed]혼란을 줄 수 있다.
어휘 해상도는 컴파일 시에 결정될 수 있으며 조기 바인딩이라고도 하며 동적 해상도는 일반적으로 실행 시에만 결정될 수 있으므로 지연 바인딩이라고도 합니다.
관련 개념
객체 지향 프로그래밍에서 동적 디스패치는 실행 시 객체 메서드를 선택합니다.단, 실제 이름 바인딩이 컴파일 시 수행되는지 런타임에 수행되는지 여부는 언어에 따라 다릅니다.사실상의 동적 범위는 매크로 언어에서 일반적으로 사용되며, 매크로 언어에서는 이름 해결을 직접 수행하지 않고 대신 제자리에 확장됩니다.
Angular와 같은 일부 프로그래밍 프레임워크JS는 "scope"라는 용어를 이 문서에서 사용되는 방법과는 완전히 다른 것을 의미합니다.이러한 프레임워크에서 스코프는 사용하는 프로그래밍 언어의 객체일 뿐입니다(각도의 경우 자바스크립트).JS) 변수에 어휘적 범위를 사용하는 언어로 동적 범위를 에뮬레이트하기 위해 프레임워크에 의해 특정 방법으로 사용됩니다.각진 사람JS 스코프는 다른 오브젝트와 마찬가지로 언어의 가변 범위 규칙과 상속 규칙과 트랜슬루전 규칙을 사용하여 프로그램의 주어진 부분에서 컨텍스트에 있을 수도 있고 컨텍스트에 있지 않을 수도 있습니다(용어의 통상적인 의미를 사용할 수도 있습니다.AngularJS에서는 혼동을 피하기 위해 "$scope"(달러 기호 포함)라는 용어를 사용하기도 하지만 스타일 가이드에서는 종종 [5]달러 기호를 사용하지 않는 경우가 있습니다.
사용하다
스코프는 이름 [d]해결의 중요한 컴포넌트이며, 이는 언어 의미론의 기초가 됩니다.이름 해결(범위 포함)은 프로그래밍 언어에 따라 다르며 프로그래밍 언어 내에서는 엔티티 유형에 따라 다릅니다.범위에 대한 규칙을 범위 규칙(또는 범위 규칙)이라고 합니다.네임스페이스와 함께 스코프 규칙은 모듈러 프로그래밍에서 매우 중요하므로 프로그램의 일부 부분을 변경해도 관련 없는 부분이 끊어지지 않습니다.
개요
범위를 설명할 때는 범위, 익스텐트 및 컨텍스트의 세 가지 기본 개념이 있습니다.특히 "Scope"와 "context"는 자주 혼동됩니다.context는 이름 바인딩의 속성인 반면, context는 소스 코드(렉트릭 컨텍스트 또는 정적 컨텍스트)의 일부 또는 런타임 컨텍스트, 호출 컨텍스트 또는 동적 컨텍스트의 일부입니다.실행 컨텍스트는 (현재 실행 포인트에서) 어휘 컨텍스트와 콜스택 [e]등의 추가 런타임 상태로 구성됩니다.엄밀히 말하면 실행 중에 프로그램이 다양한 이름 바인딩의 범위를 출입하고 실행 시 이름 바인딩이 "콘텍스트 내" 또는 "컨텍스트 외"이므로 프로그램 실행이 범위를 [f]출입할 때 이름 바인딩이 "콘텍스트 내" 또는 "콘텍스트 외"가 됩니다.그러나 실제로는 사용이 훨씬 느슨하다.
스코프는 소스 코드 수준의 개념으로 이름 바인딩, 특히 변수 또는 함수 이름 바인딩의 속성(소스 코드 내의 이름은 프로그램 내의 엔티티에 대한 참조)이며 컴파일러 또는 언어의 인터프리터 동작의 일부입니다.따라서 스코프의 문제는 포인터와 비슷하며, 포인터는 프로그램에서 일반적으로 사용되는 참조 유형입니다.이름이 컨텍스트에 있지만 변수가 초기화되지 않은 경우 변수 값을 사용하는 것은 와일드 포인터가 정의되어 있지 않기 때문에 참조 해제(값 접근)와 유사합니다.그러나 변수는 컨텍스트를 벗어날 때까지 파괴되지 않기 때문에 덩글링 포인터의 아날로그는 존재하지 않습니다.
변수 등의 엔티티에서 스코프는 라이프 타임의 서브셋(확장이라고도 함)입니다.이름은 존재하는 변수만 참조할 수 있지만 존재하는 변수는 반드시 표시할 수 있는 것은 아닙니다.변수는 존재하지만 액세스 할 수 없습니다(값은 특정 컨텍스트 내에서 저장되지만 참조할 수 없습니다).또는 액세스 할 수 없지만 v는 할 수 없습니다.ia 지정된 이름(이 경우 해당 이름이 컨텍스트에 포함되지 않음)입니다(프로그램은 "이름의 범위 밖").다른 경우 "lifetime"은 관련이 없습니다. 라벨(소스 코드의 이름 위치)은 프로그램과 수명이 동일하지만 프로그램의 특정 지점에 있거나 없을 수 있습니다. 또한 정적 글로벌 변수는 전체 프로그램에 대해 컨텍스트에 있습니다. 반면 정적 로컬 변수는 정적 로컬 변수도 마찬가지입니다.는 함수 또는 기타 로컬콘텍스트 내의 컨텍스트에만 존재하지만 둘 다 프로그램 실행 전체의 라이프타임이 있습니다.
이름이 참조하는 엔티티를 결정하는 것은 이름 해결 또는 이름 바인딩이라고 하며(특히 객체 지향 프로그래밍에서는) 언어에 따라 다릅니다.이름을 지정하면 언어(적절하게 컴파일러 또는 인터프리터)는 컨텍스트에 있는 모든 엔티티가 일치하는지 확인합니다.모호한 경우(같은 이름의 글로벌 변수 및 로컬 변수 등) 이름 해결 규칙을 사용하여 이들을 식별합니다.대부분의 경우 이름 해결은 Python LEGB(Local, Enclosing, Global, Built-in) 규칙과 같은 "내부 대 외부 컨텍스트" 규칙에 의존합니다. 즉, 이름은 가장 좁은 관련 컨텍스트로 암묵적으로 해결됩니다.경우에 따라서는, 이름 해결을 명시적으로 지정할 수 있습니다.예를 들어,global
그리고.nonlocal
Python에서는 키워드를 사용합니다.그 이외의 경우 기본 규칙을 덮어쓸 수 없습니다.
2개의 동일한 이름이 동시에 다른 엔티티를 참조하는 경우, 이름 마스킹이 발생하고 있다고 합니다.이 경우 우선순위가 높은 이름(통상은 가장 안쪽)이 우선순위가 낮은 이름을 「마스크」합니다.변수 수준에서는 이를 변수 그림자라고 합니다.마스킹에 의한 로직 에러의 가능성이 있기 때문에, 일부 언어에서는 마스킹을 허가 또는 금지하고, 컴파일 시 또는 실행 시에 에러나 경고를 발생시킵니다.
다양한 프로그래밍 언어에는 다양한 종류의 선언 및 이름에 대한 다양한 범위 규칙이 있습니다.이러한 범위 규칙은 언어 의미론 및 결과적으로 프로그램의 동작과 정확성에 큰 영향을 미칩니다.C++와 같은 언어에서는 언바인드 변수에 액세스 할 때 명확하게 정의된 시멘틱스가 없고, 언바인드 포인터와 마찬가지로 정의되지 않은 동작이 발생할 수 있습니다.또한 언바인드 변수의 범위 밖에서 사용되는 선언이나 이름은 구문 오류를 생성합니다.
스코프는 종종 다른 언어 구성 요소와 연계되어 암묵적으로 결정되지만, 많은 언어는 스코프를 제어하기 위한 구성 요소도 제공합니다.
범위 수준
범위는 하나의 표현식부터 프로그램 전체까지 다양하며, 그 사이에는 여러 가지 그라데이션이 있을 수 있습니다.가장 간단한 범위 규칙은 글로벌 범위입니다.모든 엔티티가 프로그램 전체에서 표시됩니다.가장 기본적인 모듈러 스코프 규칙은 프로그램 내 임의의 장소에 글로벌스코프가 있는 2레벨 스코프 및 기능 내 로컬스코프입니다보다 정교한 모듈 프로그래밍을 사용하면 모듈 내(모듈 전용)에는 이름이 표시되지만 모듈 외부에는 표시되지 않는 별도의 모듈 스코프가 가능합니다.함수 내에서 C와 같은 일부 언어에서는 블록 스코프가 함수의 서브셋으로 범위를 제한할 수 있으며, 다른 언어(특히 기능 언어)에서는 표현 스코프가 범위를 단일 표현으로 제한할 수 있습니다.그 외의 스코프에는, 모듈 스코프와 같이 동작하는 파일 스코프(특히 C 로), 기능외의 블록 스코프(특히 Perl 로)가 있습니다.
미묘한 문제는 스코프가 정확히 언제 시작 및 종료되는지입니다.C와 같은 일부 언어에서는 이름의 범위가 이름 선언에서 시작되므로 특정 블록 내에서 선언된 이름마다 범위가 다를 수 있습니다.이를 위해서는 함수를 반드시 정의하지는 않지만 사용 전에 함수를 선언해야 하며, 특히 상호 재귀의 경우 전진 선언이 필요합니다.Python과 같은 다른 언어에서 이름의 범위는 정의된 위치에 관계없이 이름이 선언된 관련 블록의 시작부터 시작됩니다(예를 들어 함수의 시작). 따라서 주어진 블록 내의 모든 이름은 동일한 범위를 가집니다.JavaScript에서 선언된 이름의 범위:let
또는const
이름 선언에서 시작되며, 로 선언된 이름의 범위는var
는 이름이 선언된 함수의 시작부터 시작됩니다.이것은 변수 호이스트라고 불립니다.정의되지 않은 값이 있는 컨텍스트에서 이름의 동작은 다릅니다: Python에서 정의되지 않은 이름을 사용하면 런타임 오류가 발생하는 반면 JavaScript에서는 정의되지 않은 이름이 다음과 같이 선언됩니다.var
함수가 함수에 걸쳐 사용할 수 있는 이유는 함수가 함수의 값에 암묵적으로 결합되어 있기 때문입니다.undefined
.
식범위
이름 바인딩의 범위는 expression으로, expression scope로 알려져 있습니다.표현식 범위는 여러 언어, 특히 선언의 범위를 단일 표현식으로 만들 수 있는 let-expressions라는 기능을 제공하는 기능적 언어로 제공됩니다.이것은 예를 들어 계산에 중간값이 필요한 경우에 편리합니다.예를 들어 표준 ML에서는f()
돌아온다12
,그리고나서let val x = f() in x * x end
이 표현은 다음과 같은 표현입니다.144
, 라는 이름의 임시 변수를 사용합니다.x
부르기를 피하다f()
두 번. 블록 스코프를 가진 일부 언어들은 표현식에 삽입되는 블록의 구문을 제공함으로써 이 기능에 근접합니다. 예를 들어, 앞서 언급한 표준 ML 표현식은 다음과 같이 Perl로 작성될 수 있습니다.do { my $x = f(); $x * $x }
, 또는 GNU C에서는 로서({ int x = f(); x * x; })
.
Python의 경우 생성기 식과 목록 압축(Python 3의 경우)의 보조 변수는 식 범위를 가집니다.
C에서 함수 프로토타입의 변수 이름은 함수 프로토콜 범위로 알려진 식 범위를 가집니다.프로토타입의 변수 이름은 참조되지 않기 때문에(실제 정의에서는 다를 수 있음), 단순히 더미일 뿐이므로 문서 생성에 사용될 수 있지만 생략되는 경우가 많습니다.
블록 범위
이름 바인딩의 범위는 블록 범위로 알려져 있는 블록입니다.블록 스코프는 일부 블록 구조 프로그래밍 언어에서만 사용할 수 있습니다.이것은 ALGOL 60에서 시작되었습니다.여기서 "매우 선언...이 [6]블록에 대해서만 유효합니다.".오늘날은 특히 Pascal과 C패밀리의 언어 및 전통과 관련되어 있습니다.대부분의 경우 이 블록은 함수 내에 포함되어 있기 때문에 스코프가 함수의 일부로 제한되지만 Perl과 같은 경우에 블록이 함수 내에 없을 수 있습니다.
서명되어 있지 않다 인트 합계(컨스턴트 서명되어 있지 않다 인트 N) { 서명되어 있지 않다 인트 리트 = 0; 위해서 (서명되어 있지 않다 인트 n = 1; n <=> N; n++) { 컨스턴트 서명되어 있지 않다 인트 n_interface = n * n; 리트 += n_interface; } 돌아가다 리트; }
블록 스코프 사용의 대표적인 예는 다음과 같은 C 코드입니다.여기서 2개의 변수는 루프에 스코프됩니다.루프 변수입니다n이 값은 루프가 반복될 때마다 1회씩 초기화되며 증분되며 보조 변수n_squared각 반복마다 초기화됩니다.그 목적은 특정 블록에만 관련된 함수 범위에 변수를 추가하는 것을 피하는 것입니다.예를 들어 범용 루프 변수에서 오류가 발생하는 것을 방지합니다.i실수로 이미 다른 값으로 설정되었습니다.이 예에서 표현은n * n
일반적으로 보조 변수에 할당되지 않으며, 루프의 본문은 단순히 작성됩니다.ret += n * n
그러나 더 복잡한 예에서는 보조 변수가 유용합니다.
블록은 if, while 및 루프와 같은 제어 흐름에 주로 사용되며, 이 경우 블록 범위는 함수의 실행 흐름 구조에 따라 달라집니다.그러나 블록 범위를 가진 언어에서는 일반적으로 "네이키드" 블록을 사용할 수도 있습니다.이 블록의 목적은 가변 범위를 세밀하게 제어하는 것입니다.예를 들어 보조 변수를 블록에서 정의한 후 (예를 들어 함수 범위를 가진 변수에 추가) 블록이 종료될 때 사용되거나 루프 내에서 사용되는 변수를 초기화하는 블록에 while 루프가 포함될 수 있습니다.
Algol 68 및 C(이 예에서는 시연되고 C99 이후 표준화됨)와 같은 여러 프로그래밍 언어의 미묘한 점은 블록 범위 변수가 블록 본문 내에서뿐만 아니라 제어문 내에서 선언될 수 있다는 것입니다.이는 함수 본체의 블록이 시작되기 전 함수 선언 및 함수 본체 전체의 범위에서 선언되는 함수 매개 변수와 유사합니다.이것은 주로 while loops와는 달리 루프 조건과는 다른 initialization 문이 있는 루프의 경우 사용되며 일반적인 관용어입니다.
블록 스코프는 섀도우에 사용할 수 있습니다.이 예에서는 블록 내에서 보조 변수를 호출할 수도 있습니다.n파라미터 이름을 그림자처럼 표시하지만 에러 가능성이 있기 때문에 스타일이 좋지 않은 것으로 간주됩니다.또한 Java나 C# 등 C의 일부 하위 항목에서는 블록 스코프가 지원되지만(함수가 종료되기 전에 로컬 변수를 컨텍스트 밖으로 내보낼 수 있음), 어떤 로컬 변수가 다른 변수를 숨길 수 없습니다.이러한 언어에서 두 번째 선언은n구문 오류가 발생하며,n변수 이름을 변경해야 합니다.
블록이 변수 값을 설정하는 데 사용되는 경우 블록 스코프를 사용하려면 변수를 블록 외부에 선언해야 합니다.따라서 단일 할당으로 조건문을 사용하는 것이 복잡해집니다.예를 들어 블록 스코프를 사용하지 않는 Python에서는 다음과 같이 변수를 초기화할 수 있습니다.
한다면 c: a = "푸" 또 다른: a = ""
어디에a
액세스 할 수 있는 것은,if
진술.
블록 스코프를 가진 Perl에서는 대신 블록 전에 변수를 선언해야 합니다.
나의 $a; 한다면 (c) { $a = '푸'; } 또 다른 { $a = ''; }
대부분의 경우 이 값은 여러 할당을 사용하여 다시 작성되며 변수를 기본값으로 초기화합니다.Python(필요 없는 경우)에서는 다음과 같습니다.
a = "" 한다면 c: a = "푸"
Perl에서는 다음과 같습니다.
나의 $a = ''; 한다면 (c) { $a = '푸'; }
단일 변수 할당의 경우, 대안으로 삼원 연산자를 사용하여 블록을 피하는 것이 있지만, 이는 일반적으로 다중 변수 할당에서는 가능하지 않고 복잡한 로직에서는 읽기 어렵다.
이것은 특히 문자열 할당의 경우 C에서 더 중요한 문제입니다.문자열 초기화로 메모리를 자동으로 할당할 수 있지만 이미 초기화된 변수에 대한 문자열 할당에는 메모리 할당, 문자열 복사 및 이들 할당이 성공했는지 확인해야 하기 때문입니다.
{ 나의 $카운터 = 0; 후보선수 increment_counter { 돌아가다 ++$카운터; } }
일부 언어에서는 블록 범위의 개념을 함수 외부에서 다양한 익스텐트에 적용할 수 있습니다.예를 들어 오른쪽 Perl 스니펫에서는$counter
블록 스코프를 가진 변수 이름입니다(사용에 의해).my
키워드)와increment_counter
는 글로벌 스코프를 가진 함수 이름입니다.에 대한 각 호출increment_counter
가치를 높이다$counter
새 값을 반환합니다.이 블록 외부의 코드가 호출할 수 있습니다.increment_counter
단, 다른 방법으로는 값을 취득하거나 변경할 수 없습니다.$counter
이 관용구를 사용하면 Perl에서 클로저를 정의할 수 있습니다.
기능범위
함수 내에서 선언된 변수의 범위가 해당 함수 이상으로 확장되지 않는 경우 이를 함수 [7]범위라고 합니다.함수 스코프는 함수 또는 서브루틴에서 로컬 변수를 만드는 방법을 제공하는 대부분의 프로그래밍 언어에서 사용할 수 있습니다. 이 변수는 함수가 반환될 때 스코프가 종료(콘텍스트를 벗어남)되는 변수입니다.대부분의 경우 변수의 라이프 타임은 함수 호출 기간입니다.함수가 시작되었을 때(또는 변수가 선언되었을 때) 생성되고 함수가 반환되었을 때 파기됩니다.단, 변수의 범위는 범위가 어휘인지 동적인지에 따라 함수 내에 있습니다.단, C와 같은 일부 언어에서는 정적 로컬 변수도 제공합니다.여기서 변수의 라이프 타임은 프로그램의 라이프 타임이지만 변수는 함수 내부에 있을 때만 컨텍스트에 있습니다.정적 로컬 변수의 경우, 변수는 프로그램이 초기화될 때 생성되며 정적 글로벌 변수와 같이 프로그램이 종료될 때만 파괴되지만 자동 로컬 변수와 같은 함수 내에서만 컨텍스트에 있습니다.
어휘적 범위에서 함수 범위를 가진 변수는 함수의 어휘적 컨텍스트 내에서만 범위를 갖는다: 함수 내에서 다른 함수가 호출될 때 컨텍스트를 벗어나 함수가 반환될 때 다시 컨텍스트로 돌아온다: 호출된 함수는 호출된 함수의 로컬 변수에 액세스할 수 없으며 로컬 변수는 다음과 같다.선언된 함수의 본문 내에서만 해당됩니다.반면 다이내믹 스코프에서는 스코프는 함수의 실행 컨텍스트로 확장됩니다.로컬 변수는 다른 함수가 호출되었을 때 컨텍스트에 머무르며, 정의 함수가 종료되었을 때만 컨텍스트를 벗어나 로컬 변수는 정의된 함수와 모든 함수의 컨텍스트에 있습니다.어휘 범위와 중첩 함수를 가진 언어에서 로컬 변수는 중첩된 함수에 대한 컨텍스트입니다. 왜냐하면 로컬 변수는 동일한 어휘 컨텍스트 내에 있지만 어휘적으로 중첩되지 않은 다른 함수에 대해서는 해당되지 않기 때문입니다.둘러싸인 함수의 로컬 변수는 중첩된 함수의 비 로컬 변수라고 합니다.함수 범위는 익명 함수에도 적용됩니다.
방어하다 광장(n): 돌아가다 n * n 방어하다 합계(n): 총 = 0 i = 0 하는 동안에 i <=> n: 총 += 광장(i) i += 1 돌아가다 총
예를 들어 오른쪽의 Python 코드 부분에는 두 가지 함수가 정의되어 있습니다.square
그리고.sum_of_squares
.square
숫자의 제곱을 계산합니다.sum_of_squares
는 모든 제곱의 합계를 최대 수치까지 계산합니다.(예를 들어,square(4)
42 =16
,그리고.sum_of_squares(4)
02 + 12 + 22 + 32 + 42 =30
.)
이러한 함수에는 각각 다음과 같은 변수가 있습니다.n함수에 대한 인수를 나타냅니다.이 두 사람n변수는 이름이 같지만 완전히 분리되고 관련이 없습니다.왜냐하면 변수들은 함수 범위를 가진 어휘적 범위의 로컬 변수이기 때문입니다.각각의 범위는 그 자체이며 어휘적으로 분리된 함수이기 때문에 중복되지 않습니다.그러므로,sum_of_squares
전화할 수 있다square
그 자체도 없이n변화하고 있다.유사하게,sum_of_squares
에는 이름이 붙은 변수가 있습니다.total그리고.i; 이 변수들은 범위가 한정되어 있기 때문에 이름 붙여진 어떤 변수에도 간섭하지 않습니다.total또는i다른 기능에 속할 수 있습니다.즉, 이러한 이름과 관련이 없는 이름 간에 이름이 충돌할 위험이 없습니다.
이름 마스킹이 발생하지 않았습니다. 이름 있는 변수는 하나뿐입니다.n는 스코프가 중복되지 않기 때문에 항상 컨텍스트에 있습니다.이와는 대조적으로, 동적인 범위를 가진 언어로 작성되는 유사한 단편은,n콜링 함수의 컨텍스트는, 콜링 함수의 스코프가 오버랩 해, 새로운 기능에 의해서 마스크(그림자) 됩니다.n호출된 함수에 있습니다.
함수가 퍼스트 클래스 객체이며 함수에 대해 로컬로 생성한 후 반환할 수 있는 경우 함수 범위는 훨씬 복잡합니다.이 경우 내포된 함수 내의 로컬이 아닌 변수(함수 정의의 언바인드 변수, 둘러싸인 컨텍스트 내의 변수로 해결됨)는 함수 자체뿐만 아니라 해당 컨텍스트(변수의 컨텍스트)도 반환하고 다른 컨텍스트에서 호출해야 하므로 닫힘을 만듭니다.이를 위해서는 컴파일러의 지원이 대폭 증가해야 하며 프로그램 분석이 복잡해질 수 있습니다.
파일 범위
이름 바인딩의 범위는 파일 범위로 알려져 있는 파일입니다.파일 범위는 주로 C(및 C++)에 한정됩니다.여기서 파일의 최상위 수준에서 선언된 변수와 함수의 범위는 파일 전체, 즉 선언에서 소스 파일의 마지막까지 또는 보다 정확한 변환 단위(내부 링크)에 대한 것입니다.이는 모듈 스코프의 한 형태로 볼 수 있습니다.모듈 스코프는 파일로 식별되며 보다 현대적인 언어에서는 명시적인 모듈스코프로 대체됩니다.include 문이 존재하기 때문에 내부 콘텍스트에 변수와 함수를 추가하고 그 자체가 include 문을 호출할 수 있기 때문에 파일 본문의 콘텍스트를 판별하기가 어려울 수 있습니다.
위의 C코드 스니펫에서 함수명은sum_of_squares
에 파일 범위가 있습니다.
모듈 범위
이름 바인딩의 범위는 모듈입니다.모듈 스코프라고 불립니다.모듈 스코프는 모듈러형 프로그래밍 언어로 사용할 수 있습니다.모듈(다양한 파일에 걸쳐 있을 수 있음)은 정보를 숨기고 제한된 인터페이스를 노출할 수 있기 때문에 복잡한 프로그램의 기본 단위입니다.모듈 스코프는 Modula 어족 언어에서 개척되었으며, Python(Modula의 영향을 받은)이 대표적인 현대 사례입니다.
C++와 같이 모듈에 대한 직접적인 지원이 부족한 일부 객체 지향 프로그래밍 언어에서는 클래스 계층에 의해 유사한 구조가 대신 제공되며, 여기서 클래스는 프로그램의 기본 단위이고 클래스는 개인 메서드를 가질 수 있다.이는 이름 해결 및 범위가 아닌 동적 디스패치의 맥락에서 올바르게 이해되지만, 이들은 대부분 유사한 역할을 합니다.Python에서는 모듈과 클래스를 모두 갖추고 있으며 코드 구성은 프로그래머가 선택할 수 있습니다(모듈 수준의 함수 또는 관례적인 개인 메서드).
글로벌 범위
이름 바인딩의 범위는 전체 프로그램이며, 이를 글로벌 범위라고 합니다.글로벌 스코프를 가진 변수 이름(글로벌 변수라고 불린다)은 적어도 일부 언어에서는 이름 충돌 및 의도하지 않은 마스킹의 가능성, 모듈성이 낮기 때문에 자주 잘못된 관행으로 간주되며 함수 범위 또는 블록 범위가 권장됩니다.그러나 글로벌 스코프는 일반적으로 함수 이름, 클래스 이름, 기타 데이터 유형의 이름 등 다양한 종류의 이름에 사용됩니다(언어에 따라 다름).이러한 경우 충돌을 피하기 위해 네임스페이스 등의 메커니즘을 사용합니다.
어휘 범위와 동적 범위
로컬 변수(범위가 제한된 변수 이름, 특정 함수 내에만 존재하는 변수 이름)를 사용하면 동일한 이름의 두 변수 간에 이름이 충돌하는 위험을 방지할 수 있습니다.그러나 이 질문에 대답하는 방법에는 크게 다른 두 가지가 있습니다.함수 내에 있다는 것은 무엇을 의미합니까?
어휘 범위(또는 어휘 범위, 정적 범위 또는 정적 범위라고도 함)에서 변수 이름의 범위가 특정 함수인 경우, 그 범위는 함수 정의의 프로그램 텍스트가 됩니다. 즉, 변수 이름은 텍스트 내에 존재하며 변수 값에 바인딩되지만, 해당 텍스트 외부에 변수 이름은 존재하지 않습니다.반면 동적 범위(또는 동적 범위)에서는 변수 이름의 범위가 특정 함수일 경우 해당 범위는 함수가 실행되는 기간입니다. 함수가 실행 중일 때는 변수 이름이 존재하며 함수가 반환된 후에는 변수 이름이 존재하지 않습니다.즉, 기능하는 경우f
별도로 정의된 함수를 호출하다g
, 그 후 어휘 범위에서는 함수g
에 액세스 할 수 없다.f
의 로컬 변수(텍스트 표시)g
의 텍스트 안에 없습니다.f
다이내믹 스코프 하에서는 기능합니다.g
에 액세스 할 수 있다f
의 로컬 변수(이후)g
호출 중에 호출됩니다.f
).
$# bash language $ x=1 $ function g() { echo $x ; x=2 ;} $ f() { local x=3 ; g ; } $ f # 이 인쇄물은 1, 또는 3?3 $ echo $x # 이 인쇄물은 1, 또는 2?1?
예를 들어 오른쪽에 있는 프로그램을 생각해 보십시오.첫 번째 줄,x=1
글로벌 변수를 만듭니다.x
에 초기화합니다.1
두 번째 줄,function g() { echo $x ; x=2 ; }
, 함수를 정의합니다.g
현재 가치를 출력하는 ('인쇄')x
, 그 후 설정한다.x
로.2
(이전 값을 덮어씁니다).세 번째 줄,function f() { local x=3 ; g ; }
함수를 정의합니다.f
로컬 변수를 만듭니다.x
(동일한 이름의 글로벌 변수를 삭제) 및 초기화합니다.3
를 호출합니다.g
네 번째 줄,f
, 콜f
다섯 번째 줄,echo $x
의 현재 값을 출력합니다.x
.
그럼, 이 프로그램은 정확히 뭘 인쇄하는 거죠?스코프 규칙에 따라 다릅니다.이 프로그램의 언어가 어휘 범위를 사용하는 언어일 경우,g
글로벌 변수 인쇄 및 변경x
(왜냐하면g
외부에서 정의됩니다.f
이 때문에, 프로그램이 인쇄됩니다.1
그리고 나서.2
반면 이 언어가 동적 스코프를 사용하는 경우g
인쇄 및 변경f
의 로컬 변수x
(왜냐하면g
내부에서 호출됩니다.f
이 때문에, 프로그램이 인쇄됩니다.3
그리고 나서.1
(공교롭게도 프로그램의 언어는 Bash이며 동적 스코프를 사용합니다.그래서 프로그램은 인쇄합니다.3
그리고 나서.1
어휘 범위를 사용하는 ksh93에서 동일한 코드를 실행한 경우 결과는 달라집니다.)
어휘 범위
어휘 범위에서는 이름은 항상 어휘 컨텍스트를 참조합니다.이것은 프로그램텍스트의 속성으로 언어 구현에 의해 런타임콜 스택과는 독립적입니다.이 일치에는 정적 프로그램 텍스트 분석만 필요하므로 이러한 유형의 범위를 정적 범위라고도 합니다.어휘 스코프는 Pascal, Modula-2, Ada와 같은 모든 ALGOL 기반 언어 및 ML 및 Haskell과 같은 최신 기능 언어에 표준으로 사용됩니다.그것은 또한 C 언어와 통사적, 의미적 관계에서도 사용되지만, 다른 종류의 제한이 있다.정적 스코프를 사용하면 프로그래머는 파라미터, 변수, 상수, 유형, 함수 등의 객체 참조를 단순한 이름 치환으로 추론할 수 있습니다.따라서 로컬 명명 구조를 개별적으로 이해할 수 있으므로 모듈식 코드를 만들고 그에 대한 이유를 쉽게 만들 수 있습니다.반대로 동적 스코프는 프로그래머가 모듈의 코드가 호출될 수 있는 모든 가능한 실행 컨텍스트를 예측하도록 강제합니다.
프로그램. A; 변화하다 I:정수; K:차; 절차. B; 변화하다 K:진짜; L:정수; 절차. C; 변화하다 M:진짜; 시작한다. (*스코프 A+B+C*) 끝.; (*스코프 A+B*) 끝.; (*범위 A*) 끝..
예를 들어, Pascal은 어휘 범위입니다.오른쪽에 있는 Pascal 프로그램 조각을 생각해 보십시오.변수I
는 같은 이름의 다른 변수에 의해 숨겨지지 않기 때문에 모든 점에서 볼 수 있습니다.그char
변수K
메인 프로그램에서만 볼 수 있습니다.이는 에 의해 숨겨지기 때문입니다.real
변수K
절차상 볼 수법B
그리고.C
전용. 가변L
또한 절차에서만 볼 수 있습니다.B
그리고.C
그러나 다른 변수는 숨기지 않습니다.변수M
절차에서만 볼 수 있습니다.C
따라서 절차에서도 접근할 수 없습니다.B
또는 메인 프로그램.또, 순서C
절차에서만 볼 수 있습니다.B
따라서 메인 프로그램에서는 호출할 수 없습니다.
다른 방법이 있었을 수도 있어요C
절차 외 프로그램에서 선언됨B
프로그램 중 "이곳은"C
그 후, 「」를 언급해, 다음의 2개의 순서 중 어느 쪽을 지정할지 결정합니다.C
따라서 변수의 범위와 정확히 유사합니다.
제1종 중첩 함수를 가진 언어에서 어휘 스코프의 정확한 구현은 각 함수 값이 종속된 변수 값의 기록을 가지고 있어야 하기 때문에 간단하지 않다(함수와 이 컨텍스트의 쌍은 폐쇄라고 불린다).구현 및 컴퓨터 아키텍처에 따라, 변수 룩업은 매우 깊이 있는 사전 중첩 함수를 사용할 때 약간 비효율적일[citation needed] 수 있지만, 이를 [8][9]완화하는 잘 알려진 기술이 있습니다.또한 자체 인수와 (즉시) 로컬 변수만 참조하는 중첩된 함수의 경우 컴파일 시 모든 상대 위치를 알 수 있습니다.따라서 이러한 유형의 중첩 함수를 사용할 경우 오버헤드가 전혀 발생하지 않습니다.이는 중첩된 함수를 사용하지 않는 프로그램의 특정 부분과 중첩된 함수를 사용할 수 없는 언어(C 언어 등)로 작성된 프로그램에도 적용됩니다.
역사
어휘 스코프는 1960년대 초에 명령어 ALGOL 60에 처음 사용되었고 [4]그 이후로 대부분의 다른 명령어 언어에서 채택되었다.
파스칼과 C와 같은 언어들은 모두 ALGOL 60과 ALGOL 68에 들어간 아이디어에 영향을 받았기 때문에 항상 어휘 범위를 가지고 있었다.
Perl은 나중에 정적 범위를 추가하는 동적 범위를 가진 언어입니다.
오리지널 리스프 인터프리터(1960)는 다이내믹스코프를 사용했습니다.LISP 1.5에서는 1962년경(John McCarthy 밑에서 일하는 Steve Russell이 개발한 Funarg 장치를 통해) 정적(렉시컬) 범위에 가까운 딥 바인딩이 도입되었습니다.
모든 초기 Lisps는 인터프리터를 기반으로 동적 스코프를 사용했습니다.1982년 Guy L. Steel Jr.와 Common LISP Group은 [10]공통 LISP의 개요, 지금까지의 Lisp의 역사와 다양한 구현에 대한 짧은 리뷰 및 공통 Lisp 구현이 갖춰야 할 특징에 대한 리뷰를 발표했습니다.102페이지에서 다음과 같이 읽습니다.
대부분의 LISP 구현은 기본적으로 인터프리터와 컴파일러가 서로 다른 시멘틱스를 올바른 프로그램에 할당할 수 있다는 점에서 내부적으로 일관성이 없습니다.이것은 주로 인터프리터가 모든 변수를 동적으로 스코핑하는 것으로 가정하는 반면 컴파일러는 다른 경우를 제외하고 모든 변수를 로컬로 가정한다는 사실에서 비롯됩니다.이것은 편리성과 효율성을 위해 이루어졌지만 매우 미묘한 버그를 일으킬 수 있습니다.공통 LISP의 정의는 인터프리터와 컴파일러가 올바른 프로그램에 동일한 의미를 부여하도록 명시적으로 요구함으로써 이러한 이상 현상을 방지합니다.
따라서 공통 LISP의 구현은 어휘적 범위를 가져야 했다.다시, 공통 LISP의 개요에서:
또한 Common LISP는 다음과 같은 기능을 제공합니다(대부분은 MacLisp, InterLisp 또는 Lisp Machines Lisp에서 차용). (...) 완전한 어휘 범위 변수를 제공합니다.이른바 'FUNARG 문제'[11][12]는 하향과 상향 모두 완전히 해결됐다.
공통 LISP의 개요가 출판된 바로 그 해(1982년)까지, Scheme라고 불리는 컴파일된 사전 범위 LISP의 초기 설계(Guy L. Stele Jr.)가 출판되어 컴파일러 구현이 시도되고 있었다.그 당시 리스프의 어휘적 범위는 일반적으로 구현하기에 비효율적일 것으로 우려되었다.T의 [13]역사에서 Olin Shivers는 다음과 같이 쓰고 있다.
당시 프로덕션에서 사용 중인 모든 심각한 Lisps는 동적으로 범위가 지정되었습니다.(1978년 가이 루이스 스틸 주니어가 쓴) 토끼[14] 논문을 주의 깊게 읽지 않은 사람은 아무도 어휘 범위가 날 것이라고 믿지 않았다. 심지어 그것을 읽은 소수의 사람들조차도 이것이 심각한 생산 용도로 사용될 것이라는 믿음을 조금 비약하고 있었다.
"lexical scoping"이라는 용어는 [15]1967년까지, "lexical scoping"이라는 용어는 1970년까지 거슬러 올라가며 프로젝트 MAC에서 Lisp 방언 MDL(당시 "Muddle"[16]로 알려짐)의 범위 규칙을 설명하기 위해 사용되었습니다.
동적 범위
다이내믹 스코프의 경우 이름은 실행 컨텍스트를 나타냅니다.그것은 현대 [4]언어에서는 드물다.기술적인 용어로는 각 이름에 글로벌한 바인딩 스택이 있음을 의미합니다.이름을 가진 로컬 변수 소개x
바인딩을 글로벌에 푸시하다x
스택(빈 상태일 수 있음)은 제어 플로우가 스코프를 벗어날 때 팝오프됩니다.평가 중x
모든 컨텍스트에서 항상 상위 바인딩을 생성합니다.바인딩 스택은 런타임에만 존재하기 때문에 컴파일 시에는 이 작업을 수행할 수 없습니다.이 때문에 이 유형의 스코프는 다이내믹스코프라고 불립니다.
일반적으로 특정 블록은 블록 실행 시간이 라이프 타임인 바인딩을 작성하기 위해 정의됩니다.이것에 의해 다이내믹스코프 프로세스에 스태틱스코프의 일부 기능이 추가됩니다.단, 코드 섹션은 다양한 장소와 상황에서 호출할 수 있기 때문에 처음에 변수를 사용할 때(또는 변수가 존재하는지) 어떤 바인딩이 적용되는지 판단하기가 어려울 수 있습니다.이것은 유익할 수 있다.최소지식의 원칙을 적용하면 코드는 변수 값의 이유(또는 상황)에 따라 회피하지만 변수의 정의에 따라 단순히 값을 사용한다.이러한 공유 데이터의 좁은 해석은 기능의 동작을 시스템의 현재 상태(또는 정책)에 적응시키기 위한 매우 유연한 시스템을 제공할 수 있습니다.그러나, 이 편익은 변수의 동작에 대한 가정을 신중하게 회피하는 것뿐만 아니라 이 방법으로 사용되는 모든 변수의 신중한 문서화에 의존하며, 프로그램의 다른 부분들 간의 간섭을 탐지하는 메커니즘을 제공하지 않는다.Perl이나 Common Lisp와 같은 일부 언어에서는 프로그래머가 변수를 정의하거나 재정의할 때 정적 또는 동적 범위를 선택할 수 있습니다.동적 스코프를 사용하는 언어로는 Logo, Emacs Lisp, LaTeX 및 셸 언어 bash, 대시, PowerShell 등이 있습니다.
다이내믹 스코프는 구현이 매우 용이합니다.이름 값을 찾기 위해 프로그램은 런타임 스택을 통과하여 각 활성화 레코드(각 함수의 스택 프레임)에서 이름 값을 확인할 수 있습니다.실제로는 이름/값 쌍의 스택인 연관 목록을 사용하여 이 작업을 더 효율적으로 수행할 수 있습니다.쌍은 선언이 이루어질 때마다 이 스택에 푸시되며 변수가 [17]컨텍스트를 벗어날 때마다 팝됩니다.얕은 바인딩은 중앙 참조 테이블을 사용하여 각 이름을 고유한 의미 스택과 연관짓는 훨씬 빠른 대체 전략입니다.이렇게 하면 런타임 중에 특정 이름을 찾기 위한 선형 검색이 필요하지 않지만 [17]이 테이블을 적절하게 유지 관리해야 합니다.두 방법 모두 1개의 변수에 대한 바인딩에 대한 Last-In-First-Out(LIFO; 라스트인퍼스트아웃) 순서를 전제로 하고 있습니다.실제로는 모든 바인딩이 그렇게 되어 있습니다.
더 간단한 구현은 단순한 글로벌 변수를 사용하여 동적 변수를 표현하는 것입니다.로컬 바인딩은 프로그램에서 보이지 않는 스택의 익명 위치에 원래 값을 저장함으로써 수행됩니다.바인딩 범위가 종료되면 원래 값이 이 위치에서 복원됩니다.실제로 다이내믹 스코프는 이러한 방식으로 생성되었습니다.Lisp의 초기 구현은 로컬 변수를 구현하기 위해 이 명백한 전략을 사용했으며, GNU Emacs Lisp와 같은 일부 방언에서 여전히 사용되고 있습니다.Lexical Scope는 나중에 Lisp에 도입되었습니다.이는 중앙 참조 테이블이 단순히 글로벌 변수 바인딩 컨텍스트이며 변수의 현재 의미가 글로벌 값이라는 점을 제외하고 위의 얕은 바인딩 방식과 동일합니다.글로벌 변수의 유지보수는 복잡하지 않습니다.예를 들어, 기호 개체는 전역 값을 위한 전용 슬롯을 가질 수 있습니다.
다이내믹 스코프는 스레드 로컬 스토리지에 뛰어난 추상화를 제공하지만, 이 방법을 사용할 경우 글로벌 변수의 저장 및 복원을 기반으로 할 수 없습니다.가능한 구현 전략은 각 변수에 스레드 로컬 키를 갖는 것입니다.변수에 액세스할 때 스레드 로컬 키가 스레드 로컬 메모리 위치에 액세스하기 위해 사용됩니다(컴파일러에 의해 생성된 코드에 의해 어떤 변수가 동적이고 어떤 변수가 어휘인지 알 수 있습니다.발신측 스레드에 스레드 로컬키가 존재하지 않는 경우 글로벌로케이션이 사용됩니다.변수가 로컬로 바인드되어 있는 경우 이전 값은 스택의 숨겨진 위치에 저장됩니다.스레드 로컬 저장소가 변수의 키 아래에 생성되고 새 값이 저장됩니다.이 스레드 내에 있는 변수의 추가 중첩 오버라이드는 이 스레드 로컬 위치를 저장하고 복원하기만 하면 됩니다.첫 번째 가장 바깥쪽 오버라이드 컨텍스트가 종료되면 스레드 로컬키가 삭제되어 변수의 글로벌버전이 다시 스레드에 표시됩니다.
참조 투과성을 사용하면 동적 범위는 현재 함수의 인수 스택으로만 제한되며 어휘 범위와 일치합니다.
매크로 확장
현대 언어에서 프리프로세서의 매크로 확장은 사실상의 동적 범위의 주요 예입니다.매크로 언어 자체는 이름을 해결하지 않고 소스 코드만 변환하지만, 확장이 제자리이기 때문에 확장 텍스트의 이름이 해결되면(특히 자유 변수), 동적 스코프가 발생하는 것처럼 확장되는 위치에 따라 해결됩니다('불필요한' 호출됨').
매크로 확장에 사용되는 C 프리프로세서는 이름 해결이 자체적으로 이루어지지 않고 매크로가 정의되어 있는 장소와는 무관하기 때문에 사실상 다이내믹스코프를 갖추고 있습니다.예를 들어, 매크로:
#정의 ADD_A(x) x + a
확장하여 추가합니다.a
이 이름은 나중에 매크로의 위치를 기반으로 컴파일러에 의해서만 해결됩니다.ADD_A
는 "called"(호출, 확장)입니다.C 프리프로세서는 어휘 분석만 수행하고 토큰화 단계에서는 매크로를 확장하며 구문 트리로 해석하거나 이름 해결을 수행하지 않습니다.
예를 들어, 다음 코드에서 이름은a
(확장 후) 매크로에서 확장 사이트의 로컬 변수로 해결됩니다.
#정의 ADD_A(x) x + a 공백 add_1(인트 *x) { 컨스턴트 인트 a = 1; *x = ADD_A(*x); } 공백 추가_2(인트 *x) { 컨스턴트 인트 a = 2; *x = ADD_A(*x); }
수식자명
지금 여러분이 보고, 한가지 범위는 주요한 이유 중 동일한 이름의 뚜렷한 것에 제한을 이름이 별도의 범위가 있어야 해 참조할 수 있도록 하여 이름 충돌을 막도록 도와 준다.많은 다른 상황들이 프로그램 동안 계속해서 접근성이 필요할 때때로 이러한 제약, 불편하다, 그들은 일반적으로 모든, 너무나도 다른 기술 이름 충돌을 피하기 위해 필요하다 전역 범위로 이름이 필요하다.
이 문제를 해결하기 위해, 많은 언어 세계적인 이름 정리하기 위해 메커니즘을 제공한다.이러한 메커니즘의 구체적 내용과 용어를 쓰지만 언어에, 그 일반적인 생각 이름의 그룹 자체가 접두사 — —고, 필요할 때, 실체에 자격 있는 이름은 이름과 접두사로 구성된에 의해 참조될 수 있는 이름을 줄 수 있다는 의존한다.보통 그런 이름들을, 어떤 의미에서, 그리고 두개 이상의 더 좁은 범위가 자격이 없는 이름(그 접두사 없이)도 볼수는 두 사람의:정규화된 이름 보일 수 있는 범위(보통 전역 범위)를 가질 것이다.그리고 보통 단체들이 그룹으로, 즉 그들이 중첩될 수 있는 이루어질 수 있다.
많은 언어가 이 개념을 지원하지만 세부 사항은 크게 다릅니다.일부 언어에는 C++ 및 C#의 네임스페이스와 같은 메커니즘이 있어 글로벌 이름을 그룹으로 정리할 수 있습니다.다른 언어에는 Ada의 패키지나 Standard ML의 구조 등의 메커니즘이 있으며, 이를 그룹의 다른 구성원에게만 일부 이름을 표시할 수 있도록 하는 추가 목적과 결합합니다.오브젝트 지향 언어에서는 클래스나 싱글톤 오브젝트가 이 목적을 달성할 수 있는 경우가 많습니다(이것이 주된 목적인 메카니즘을 가지고 있는지 여부).게다가, 언어들은 종종 이러한 접근 방식을 혼합합니다. 예를 들어 Perl의 패키지는 C++의 네임스페이스와 비슷하지만 선택적으로 객체 지향 프로그래밍을 위한 클래스로서 두 배가 됩니다. Java는 변수와 함수를 클래스로 정리하지만 그런 클래스를 Ada와 유사한 패키지로 정리합니다.
언어별
이 섹션은 확장해야 합니다.추가해서 도움을 드릴 수 있습니다. (2013년 4월) |
대표 언어의 범위 규칙은 다음과 같습니다.
C
C에서 스코프는 일반적으로 링크 또는 가시성으로 알려져 있으며, 특히 변수의 경우 그렇습니다.C는 글로벌스코프(외부 링크), 모듈스코프 또는 파일스코프의 형식(내부 링크), 로컬스코프(함수내)를 가진 어휘 스코프 언어입니다.기능 스코프는 블록스코프를 통해 더 네스트 할 수 있습니다.그러나 표준 C는 중첩된 함수를 지원하지 않습니다.
변수의 수명 및 가시성은 해당 스토리지 클래스에 따라 결정됩니다.C에는 스태틱(프로그램 실행), 자동(블록 실행, 스택에 할당) 및 수동(히프에 할당)의 3가지 라이프타임이 있습니다.변수에 대해서는 static과 automatic만 지원되며 컴파일러에 의해 처리됩니다.단, 수동으로 할당된 메모리는 여러 변수에 걸쳐 수동으로 추적해야 합니다.C에는 외부 링크(글로벌), 내부 링크(대략 파일) 및 블록 스코프(함수 포함)의 3가지 가시성 레벨이 있습니다.블록 스코프는 네스트 할 수 있으며 include를 사용하여 다양한 수준의 내부 링크가 가능합니다.C의 내부 링크는 변환 유닛레벨에서의 가시성, 즉 C 프리프로세서에 의해 처리된 후의 소스 파일, 특히 관련된 모든 것을 포함합니다.
C 프로그램은 개별 객체 파일로 컴파일되며 링커를 통해 실행 파일 또는 라이브러리에 링크됩니다.따라서 이름 해결은 컴파일러로 분할되어 번역 유닛 내의 이름을 해결합니다(더 느슨하게는 "컴파일 유닛"이지만 이는 적절한 다른 개념입니다). 자세한 내용은 링크를 참조하십시오.
C에서 블록 스코프를 가진 변수는 선언되면 컨텍스트에 들어가고(블록의 상단이 아님), 블록 내에서 (내포되지 않은) 함수가 호출되면 컨텍스트에 들어가고 함수가 반환되면 컨텍스트에 들어가 블록의 마지막에 컨텍스트를 벗어납니다.자동 로컬 변수의 경우 선언 시 할당되고 블록 끝에 할당 해제되며 정적 로컬 변수의 경우 프로그램 초기화 시 할당되고 프로그램 종료 시 할당 해제됩니다.
다음 프로그램은 블록 스코프가 블록을 통과하는 도중에 컨텍스트에 들어온 후 블록이 종료되면 컨텍스트를 종료(실제로 할당 해제됨)하는 변수를 보여 줍니다.
#실패하다 <stdio.h> 인트 주된(공백) { 차 x = 'm'; 인쇄물(%c\n", x); { 인쇄물(%c\n", x); 차 x = 'b'; 인쇄물(%c\n", x); } 인쇄물(%c\n", x); }
프로그램 출력:
m m b m
C에는 [18]다른 수준의 범위가 있습니다.함수 프로토타입에 사용되는 변수 이름은 함수 프로토타입 가시성을 가지며 함수 프로토타입의 끝에 종료 컨텍스트가 있습니다.이 이름은 사용되지 않기 때문에 컴파일에는 유용하지 않지만 문서 작성에는 유용할 수 있습니다.GOTO 문의 라벨 이름에는 함수 범위가 있으며 스위치 문의 케이스 라벨 이름에는 블록 범위(스위치의 블록)가 있습니다.
C++
프로그램에서 사용하는 모든 변수는 a, b 및 결과가 type int임을 선언했을 때 함수 메인의 본문 선두에 있는 이전 코드에서와 같이 코드의 이전 포인트에서 유형 지정자를 사용하여 선언되어야 합니다.변수는 글로벌스코프 또는 로컬스코프 중 하나입니다.글로벌 변수는 소스 코드의 본문에 선언된 변수이며 모든 함수 외부에 선언된 변수이며 로컬 변수는 함수 또는 블록의 본문에 선언된 변수입니다.
최신 버전에서는 중첩된 어휘 범위를 사용할 수 있습니다.
재빠르다
Swift는 C++를 사용하는 범위에 대해 유사한 규칙을 가지고 있지만 다른 액세스 수식자를 포함합니다.
수식자 | 즉시 범위 | 파일 | 모듈/패키지 포함 | 다른 나라 |
---|---|---|---|---|
열다. | 네. | 네. | 네. | 네, 서브클래스를 허용합니다. |
일반의 | 네. | 네. | 네. | 예, 서브클래스를 허용하지 않습니다. |
내부의 | 네. | 네. | 네. | 아니요. |
파일프라이빗 | 네. | 네. | 아니요. | 아니요. |
사적인 | 네. | 아니요. | 아니요. | 아니요. |
가세요
자바
Java는 어휘 범위입니다.
Java 클래스에는 다음 세 가지 유형의 [19]변수를 포함할 수 있습니다.
- 로컬 변수
- 메서드 또는 특정 블록 내에서 정의됩니다.이러한 변수는 정의된 위치 및 하위 수준에 대해 로컬입니다.예를 들어 메서드 내부의 루프는 해당 메서드의 로컬 변수를 사용할 수 있지만 그 반대는 사용할 수 없습니다.루프의 변수(그 루프의 로컬)는 루프가 종료되는 즉시 파기됩니다.
- 멤버 변수
- 필드라고도 불리는 것은 클래스 내에서 선언된 변수이며 메서드 외부에 있습니다.기본적으로는 이러한 변수는 해당 클래스 내의 모든 메서드 및 패키지의 모든 클래스에 사용할 수 있습니다.
- 파라미터
- 는 메서드 선언의 변수입니다.
일반적으로 괄호 세트는 특정 범위를 정의하지만 클래스 내의 최상위 수준 변수는 정의에 사용되는 수식자 키워드에 따라 동작이 다를 수 있습니다.다음 표는 각 [20]수식자에 의해 허용된 멤버에 대한 액세스를 보여 줍니다.
수식자 | 학급 | 패키지 | 서브클래스 | 세계 |
---|---|---|---|---|
일반의 | 네. | 네. | 네. | 네. |
보호되고 있다 | 네. | 네. | 네. | 아니요. |
(수식자 없음) | 네. | 네. | 아니요. | 아니요. |
사적인 | 네. | 아니요. | 아니요. | 아니요. |
자바스크립트
자바 스크립트와 이름 확인 규칙 문제를 일으킬 수 있고의 폐쇄하려면 코트 샘플 및 팁을 널리 이용한 기능의(이름을 건 reso에 부적절한 것이 있을 때 정의된(이름을 해상도에 사용된다)은 어휘 문맥에서 다를 수 있는 어휘 문맥 의미한다 단순한 범위 rules,[21]지만 변수 초기화하고 있다.lution)의 경우 JavaScript 오브젝트에는 속성의 이름 확인이 있습니다만, 이것은 다른 토픽입니다.
JavaScript에는 함수 수준에서 중첩된 어휘적 범위가 있으며 글로벌 컨텍스트는 가장 바깥쪽 컨텍스트입니다.이 스코프는 변수와 함수 모두에 사용됩니다([23]함수 유형의 변수가 아닌 함수 선언을 의미합니다).를 사용하여 범위를 차단합니다.let
그리고.const
ECMAScript 6 이후 키워드는 표준입니다.블록 스코프는 블록 전체를 함수로 감싸고 실행함으로써 생성할 수 있습니다.이것은 IIFE(즉시 호출 함수 표현) 패턴이라고 불립니다.
JavaScript의 범위는 단순하고 기능 수준이지만 관련 초기화 및 이름 해결 규칙이 혼동을 일으킵니다.우선 스코프에 포함되지 않은 이름에 할당하면 기본적으로 로컬 변수가 아닌 새 글로벌 변수가 생성됩니다.둘째, 새로운 로컬 변수를 작성하려면var
키워드를 지정합니다.변수는 함수 상단에 value와 함께 작성됩니다.undefined
할당식에 도달하면 변수에 값이 할당됩니다.
- Initializer가 있는 변수에는 변수 [24]생성 시가 아니라 VariableStatement 실행 시 AssignmentExpression 값이 할당됩니다.
이를 변수 호이스트라고[25] 합니다.초기화가 아닌 선언이 함수의 맨 위로 호이스트됩니다.셋째, 초기화 전 변수에 대한 접근 수율undefined
구문 오류가 아닌.넷째, 함수 선언은 변수 초기화와는 달리 선언과 초기화가 모두 함수의 맨 위에 호이스트된다.예를 들어, 다음 코드에서는 로컬 변수 선언이 중단되고 글로벌 변수가 음영 처리될 때 output과 함께 대화상자가 생성되지만, 초기화는 그렇지 않기 때문에 사용할 때 변수는 정의되지 않습니다.
a = 1; 기능. f() { 경계.(a); 변화하다 a = 2; } f();
또한 함수는 JavaScript에서 퍼스트 클래스 객체이며 콜백으로 할당되거나 함수에서 반환되는 경우가 많기 때문에 함수가 실행될 때 이름 해결은 호출되는 어휘 컨텍스트나 실행 컨텍스트가 아니라 원래 정의된 위치(정의의 어휘 컨텍스트)에 따라 달라집니다.JavaScript에서 특정 함수(가장 글로벌에서 가장 로컬로)의 중첩된 범위, 특히 콜백으로 사용되는 폐쇄는 개체의 원형 체인과 유사하게 스코프 체인이라고도 합니다.
함수는 1등급 [26]객체이므로 중첩 함수를 사용하여 JavaScript에서 클로저를 생성할 수 있습니다.엔클로징 함수에서 네스트된 함수를 반환하는 것은 반환된 함수의 (비 로컬) 어휘 컨텍스트로서 엔클로징 함수의 로컬 변수를 포함하며, 클로징을 산출한다.예를 들어 다음과 같습니다.
기능. new카운터() { // 콜 시 증가하는 카운터를 반환합니다(0부터 시작). // 새 값이 반환됩니다. 변화하다 a = 0; 변화하다 b = 기능.() { a++; 돌아가다 a; }; 돌아가다 b; } c = new카운터(); 경계.(c() + ' ' + c()); // 출력 "1 2"
폐쇄는 콜백에 사용되기 때문에 JavaScript에서 자주 사용됩니다.실제로, 로컬 컨텍스트에서 함수를 콜백으로 후킹하거나 함수에서 함수를 반환하면 함수 본체에 (현재 어휘 컨텍스트의 중첩된 범위 또는 "스코프 체인"에 기초한 폐쇄 컨텍스트를 사용하여) 결합되지 않은 변수가 있는 경우 폐쇄가 생성된다. 이는 우연일 수 있다.파라미터에 따라 콜백을 작성할 때는 파라미터를 클로저에 저장해야 합니다.저장하지 않으면 인클로저 컨텍스트 내의 변수를 참조하는 클로저가 우발적으로 작성되어 [27]변경될 수 있습니다.
JavaScript 객체의 속성 이름 해결은 프로토타입 트리의 상속(트리의 루트에 대한 경로를 프로토타입 체인이라고 함)을 기반으로 하며 변수 및 함수의 이름 해결과는 별개입니다.
리스프
리스프 방언에는 범위에 대한 다양한 규칙이 있습니다.
원래 Lisp는 동적 스코프를 사용했습니다.Lisp 패밀리에 정적(렉시컬) 스코프를 도입한 것은 ALGOL에서 영감을 얻은 Scheme입니다.
Maclisp는 인터프리터에서는 기본적으로 동적 스코프를 사용하고 컴파일된 코드에서는 기본적으로 어휘 스코프를 사용하지만 컴파일된 코드는 다음을 사용하여 동적 바인딩에 액세스할 수 있습니다.SPECIAL
특정 [28]변수에 대한 선언입니다.그러나 Maclisp은 현대 언어에서 예상하는 것보다 어휘 바인딩을 최적화로 취급했으며, 현대 Lisps에서 어휘 범위로 기대할 수 있는 폐쇄 기능을 제공하지 않았다.별도의 작전,*FUNCTION
는,[29] 그 문제의 일부에 대해서 다소 서투른 대처가 가능했습니다.
Common Lisp는 [30]Scheme의 어휘 범위를 Clojure와 같이 채택했다.
ISLISP에는 일반 변수에 대한 어휘적 범위가 있다.동적 변수도 있지만 모든 경우에 명시적으로 표시되어 있습니다.defdynamic
로 묶인 특수한 형식dynamic-let
특수 형식 및 명시적 접근dynamic
특수 [31]형식
Emacs Lisp와 같은 Lisp의 일부 다른 방언에서는 여전히 기본적으로 다이내믹스코프가 사용됩니다.Emacs Lisp는 이제 버퍼 [32]단위로 어휘 범위를 사용할 수 있게 되었습니다.
파이썬
변수의 경우 Python은 함수 범위, 모듈 범위 및 글로벌 범위를 가지고 있습니다.이름은 스코프 시작 시 컨텍스트(함수, 모듈 또는 글로벌스코프)에 입력되며 내포되지 않은 함수가 호출되거나 스코프가 종료되면 컨텍스트를 종료합니다.변수 초기화 전에 이름을 사용하면 런타임 예외가 발생합니다.변수에 단순히 액세스(할당되지 않음)하는 경우 이름 해결은 가장 좁은 관련 컨텍스트로 이름을 해결하는 LEGB(Local, Enclosing, Global, Built-in) 규칙을 따릅니다.단, 변수가 할당되어 있는 경우 기본적으로 할당이 아닌 수준 시작(함수, 모듈 또는 글로벌)에서 스코프가 시작되는 변수를 선언합니다.이 두 규칙 모두 다음 명령어를 사용하여 덮어쓸 수 있습니다.global
또는nonlocal
(Python 3의 경우) 사용 전 선언을 통해 마스킹 비로컬 변수가 있더라도 글로벌 변수에 액세스하여 글로벌 변수 또는 비로컬 변수에 할당할 수 있습니다.
간단한 예로 함수는 변수를 글로벌 스코프로 해결합니다.
>>>방어하다 f(): ... 인쇄물(x) ... >>>x = "글로벌" >>>f() 세계적인
주의:x
사전에 정의되어 있습니다.f
호출되므로 에러는 발생하지 않습니다.단, 에러의 정의에서는 참조 후에 정의됩니다.f
어휘적으로 이것은 Python에서 허용되는 순방향 참조입니다.
여기서 할당은 글로벌 변수 값은 변경하지 않는 새로운 로컬 변수를 만듭니다.
>>>방어하다 f(): ... x = "f" ... 인쇄물(x) ... >>>x = "글로벌" >>>인쇄물(x) 세계적인 >>>f() f >>>인쇄물(x) 세계적인
함수 내의 변수에 할당하면 해당 변수가 함수에 대해 로컬로 선언되기 때문에 해당 함수의 범위가 함수 전체이므로 이 할당 전에 변수를 사용하면 오류가 발생합니다.이는 로컬 변수의 범위가 선언으로 시작하는 C와는 다릅니다.이 코드는 에러를 발생시킵니다.
>> def f(): ... print (x) ... x = "f"...>>> x = "global" >>> f() 트레이스백(최신 콜의 마지막):f Unbound Local Error의 <module> 파일 "<stdin>", 줄 2의 파일 "<stdin>", 줄 1: 로컬 변수 "x"가 할당 전에 참조됨
디폴트 이름 해결 규칙은 다음 명령어에 의해서 덮어쓸 수 있습니다.global
또는nonlocal
(Python 3의 경우) 키워드를 지정합니다.다음 코드에서는global x
에 있어서의 선언.g
라는 의미이다x
는 글로벌 변수로 해결됩니다.따라서 새로운 로컬 변수를 선언하지 않고 (이미 정의된 대로) 액세스하여 할당이 글로벌 변수에 할당될 수 있습니다.주의: 아니요global
에서는 선언이 필요하다f
: 변수에 할당되지 않기 때문에 기본적으로 글로벌 변수에 대한 해결이 됩니다.
>>>방어하다 f(): ... 인쇄물(x) ... >>>방어하다 g(): ... 세계적인 x ... 인쇄물(x) ... x = "g" ... >>>x = "글로벌" >>>f() 세계적인 >>>g() 세계적인 >>>f() g
global
중첩된 함수에도 사용할 수 있습니다.비내스트 함수와 같이 글로벌 변수에 대한 할당을 허용하는 것 외에 로컬 변수가 없는 경우 글로벌 변수에 액세스하기 위해서도 사용할 수 있습니다.
>>>방어하다 f(): ... 방어하다 g(): ... 세계적인 x ... 인쇄물(x) ... x = "f" ... g() ... >>>x = "글로벌" >>>f() 세계적인
중첩된 함수의 경우,nonlocal
선언, 로컬이 아닌 변수에 할당하기 위한 것으로, 를 사용하는 것과 유사합니다.global
비내포함수:
>>>방어하다 f(): ... 방어하다 g(): ... 로컬이 아닌 x # Python 3만 ... x = "g" ... x = "f" ... g() ... 인쇄물(x) ... >>>x = "글로벌" >>>f() g >>>인쇄물(x) 세계적인
R
자유변수 값이 글로벌 변수 집합에 의해 결정되는 반면, R에서는 함수가 생성된 컨텍스트에 의해 결정되는 S의 다른 구현과는 달리, R은 어휘 범위 언어이다.[33]스코프 콘텍스트에는, 다양한 기능을 사용해 액세스 할 수 있습니다(예를 들면,parent.frame()
프로그래머가 원할 경우 동적 스코프의 경험을 시뮬레이션할 수 있습니다.
블록 범위는 없습니다.
a <-> 1 { a <-> 2 } 메세지(a) ## 2
함수는 작성된 범위에 액세스할 수 있습니다.
a <-> 1 f <-> 기능.() { 메세지(a) } f() ## 1
함수 내에서 생성되거나 수정된 변수는 해당 함수에 머무릅니다.
a <-> 1 f <-> 기능.() { 메세지(a) a <-> 2 메세지(a) } f() ## 1 ## 2 메세지(a) ## 1
함수 내에서 생성되거나 수정된 변수는 포함된 범위에 대한 할당이 명시적으로 요청되지 않는 한 해당 함수에 머무릅니다.
a <-> 1 f <-> 기능.() { 메세지(a) a <<-> 2 메세지(a) } f() ## 1 ## 2 메세지(a) ## 2
R에는 디폴트 어휘 스코프가 있습니다만, 함수 스코프는 다음과 같이 변경할 수 있습니다.
a <-> 1 f <-> 기능.() { 메세지(a) } my_env <-> 새로운 환경() my_env$a <-> 2 f() ## 1 환경(f) <-> my_env f() ## 2
「 」를 참조해 주세요.
- 클로저(컴퓨터 사이언스)
- 전역 변수
- 로컬 변수
- 표현하게 하다
- 비로컬 변수
- 이름 바인딩
- 이름 해결(프로그래밍 언어)
- 변수(범위 및 범위)
- 정보 숨김
- Javascript에서 즉시 호출된 함수 표현
- 오브젝트 라이프 타임
메모들
- ^ 「범위」와 「콘텍스트」의 의미에 대해서는, 정의를 참조해 주세요.
- ^ "동적 범위"는 범위가 아닌 범위(라이프타임)에 따라 이름 해결이 이루어지기 때문에 공식적으로 부정확합니다.
- ^ 예를 들어 Python용 Jinja 템플릿엔진은 기본적으로 사전 스코프(가져오기용)와 동적 스코프(포함용)를 모두 사용하며 키워드를 사용하여 동작을 지정할 수 있습니다.「콘텍스트의 동작 Import」을 참조해 주세요.
- ^ "이름 해결"과 "이름 바인딩"은 대부분 동의어입니다. 좁게 말하면 "해결"은 고차 추상 구문에서와 같이 어떤 의미와 관련지어지지 않고 특정 이름의 사용이 참조되는 이름을 결정하는 반면, "바인딩"은 이름을 실제 의미와 관련짓습니다.실제로는 이 용어들을 서로 바꿔서 사용한다.
- ^ 자체 수정 코드의 경우 실행 시 사전 컨텍스트 자체가 변경될 수 있습니다.
- ^ 반면 *"이름 바인딩의 컨텍스트", *"범위에 들어가는 이름 바인딩" 또는 *"범위를 벗어나는 이름 바인딩"은 모두 올바르지 않습니다. 이름 바인딩에는 범위가 있지만 프로그램의 일부에는 컨텍스트가 있습니다.
레퍼런스
이 글은 검증을 위해 추가 인용문이 필요합니다. : 사이언스 · · · 학자 · (2008년 12월 (이 및 ) |
- ^ "알고리즘 언어 알골 60에 관한 보고서", 2.7. 수량, 종류 및 범위
- ^ WG14 N1256 (2007년 C99 표준 갱신판), 6.2.1 식별자 범위, 2007-09-07
- ^ a b Go 프로그래밍 언어 사양:선언 및 범위, 2013년 11월 13일 버전
- ^ a b c Borning A. CSE 341 -- Lexical 및 Dynamic Scoping.워싱턴 대학교.
- ^ Crockford, Douglas. "Code Conventions for the JavaScript Programming Language". Retrieved 2015-01-04.
- ^ Backus, J. W.; Wegstein, J. H.; Van Wijngaarden, A.; Woodger, M.; Bauer, F. L.; Green, J.; Katz, C.; McCarthy, J.; Perlis, A. J.; Rutishauser, H.; Samelson, K.; Vauquois, B. (1960). "Report on the algorithmic language ALGOL 60". Communications of the ACM. 3 (5): 299. doi:10.1145/367236.367262. S2CID 278290.
- ^ "Functions - Javascript:MDN".
Variables defined inside a function cannot be accessed from anywhere outside the function, because the variable is defined only in the scope of the function. However, a function can access all variables and functions defined inside the scope in which it is defined.
- ^ "Programming Language Pragmatics", LeBlank-Cook 기호 표
- ^ "명시적 범위 제어로 언어를 구현하기 위한 기호 테이블 추상화", LeBlank-Cook, 1983
- ^ Louis Steele, Guy (August 1982). "An overview of Common LISP". LFP '82: Proceedings of the 1982 ACM Symposium on LISP and Functional Programming: 98–107. doi:10.1145/800068.802140. ISBN 0897910826. S2CID 14517358.
- ^ Joel, Moses (June 1970). "The Function of FUNCTION in LISP". MIT AI Memo 199. MIT Artificial Intelligence Lab.
- ^ Steele, Guy Lewis Jr.; Sussman, Gerald Jay (May 1978). "The Art of the Interpreter; or, The Modularity Complex (Parts Zero, One and Two)". MIT AI Memo 453. MIT Artificial Intelligence Lab.
- ^ Shivers, Olin. "History of T". Paul Graham. Retrieved 5 February 2020.
- ^ Steele, Guy Lewis Jr. (May 1978). "RABBIT: A Compiler for SCHEME". MIT. hdl:1721.1/6913.
{{cite journal}}
:Cite 저널 요구 사항journal=
(도움말) - ^ "Lexical scope", 컴퓨터 및 프로그램 구성, 파트 3, 페이지 18, 미시건 대학교 Google Books.엔지니어링 서머 컨퍼런스, 1967
- ^ Google Books, 1970년 Project MAC Progress Report, Volume 8, 페이지 80, "lexical Scoping",
- ^ a b Scott 2009, 3.4 구현 범위, 페이지 143.
- ^ "Scope", Linux, IBM용 XL C/C++ V8.0
- ^ "Declaring Member Variables (The Java™ Tutorials > Learning the Java Language > Classes and Objects)". docs.oracle.com. Retrieved 19 March 2018.
- ^ "Controlling Access to Members of a Class (The Java™ Tutorials > Learning the Java Language > Classes and Objects)". docs.oracle.com. Retrieved 19 March 2018.
- ^ "Javascript 변수 범위에 대해 알아야 할 모든 것", Saurab Parakh, Coding is Cool, 2010-02-08
- ^ "Annotated ES5". es5.github.io. Retrieved 19 March 2018.
- ^ "Functions". MDN Web Docs. Retrieved 19 March 2018.
- ^ "12.2 Variable Statement", ECMAScript 5.1, 최종 갱신일 : 2012-05-28
- ^ "JavaScript Scoping and Hoisting", Ben Cherry, Afficiently Good, 2010-02-08
- ^ 자바스크립트 클로저즈, 리처드 콘포드입니다2004년 3월
- ^ "JavaScript 범위 및 폐쇄 설명", Robert Nyman, 2008년 10월 9일
- ^ Pitman, Kent (December 16, 2007). "The Revised Maclisp Manual (The Pitmanual), Sunday Morning Edition". MACLISP.info. HyperMeta Inc. Declarations and the Compiler, Concept "Variables". Retrieved October 20, 2018.
If the variable to be bound has been declared to be special, the binding is compiled as code to imitate the way the interpreter binds variables
- ^ Pitman, Kent (December 16, 2007). "The Revised Maclisp Manual (The Pitmanual), Sunday Morning Edition". MACLISP.info. HyperMeta Inc. The Evaluator, Special Form
*FUNCTION
. Retrieved October 20, 2018.*FUNCTION
is intended to help solve the “funarg problem,” however it only works in some easy cases. - ^ Pitman, Kent; et al. (webbed version of ANSI standard X3.226-1994) (1996). "Common Lisp HyperSpec". Lispworks.com. LispWorks Ltd. 1.1.2 History. Retrieved October 20, 2018.
MacLisp improved on the Lisp 1.5 notion of special variables ... The primary influences on Common Lisp were Lisp Machine Lisp, MacLisp, NIL, S-1 Lisp, Spice Lisp, and Scheme.
- ^ "Programming Language ISLISP, ISLISP Working Draft 23.0" (PDF). ISLISP.info. 11.1 The lexical principle. Retrieved October 20, 2018.
Dynamic bindings are established and accessed by a separate mechanism (i.e.,
defdynamic
,dynamic-let
, anddynamic
). - ^ "Lexical Binding". EmacsWiki. Retrieved October 20, 2018.
Emacs 24 has optional lexical binding, which can be enabled on a per-buffer basis.
- ^ "R FAQ". cran.r-project.org. Retrieved 19 March 2018.
- Abelson, Harold; Sussman, Gerald Jay; Sussman, Julie (1996) [1984]. Structure and Interpretation of Computer Programs. Cambridge, MA: MIT Press. ISBN 0-262-51087-1.
- Scott, Michael L. (2009) [2000]. Programming Language Pragmatics (Third ed.). Morgan Kaufmann Publishers. ISBN 978-0-12-374514-9.
- 3장: 이름, 범위 및 바인딩, 페이지 111–174
- 섹션 13.4.1: 스크립트 언어:혁신적인 기능:이름 및 범위, 페이지 691–699