바인딩, 스코프, 셀, 변경

모든 어휘 바인딩은 변경 가능한 셀입니다. 클로저는 프레임을 캡처합니다. 그래서 같은 셀에 나중에 `set!`으로 쓴 값을 함께 봅니다.

언제 필요한가요?

바인딩은 결과에 이름을 붙일 때, 로컬 스코프를 만들 때, 호출과 호출 사이의 상태를 일부러 남겨 둘 때 씁니다. 대부분의 코드는 definelet이면 충분합니다. set!은 공유 변경이 모델의 일부일 때만 꺼내세요.

실행으로 확인하기

LISPEX
(define x 1)
(define get (lambda () x))
(set! x 2)
(get)

관측 결과

OUTPUT
2

예제 읽기

get이 들고 있는 것은 숫자 1을 복사해 얼려 둔 값이 아닙니다. 이 프로시저는 x라는 이름의 전역 셀을 닫아 둡니다. set!이 바로 그 셀에 2를 쓰므로 뒤이은 호출은 2를 봅니다. 안쪽에 새 x를 만들었다면 기존 셀을 바꾸지 않고 가리기만 합니다.

이 순서로 생각하세요

  • 조회는 가장 가까운 어휘 셀을 고릅니다. 섀도잉은 바깥 바인딩을 바꾸지 않습니다.
  • letrec은 초기식보다 먼저 셀을 할당합니다. 아직 초기화되지 않은 셀을 읽으면 E321이 납니다.
  • 최상위에서 define을 다시 쓰면 기존 전역 셀을 갱신합니다. 그래서 앞서 만든 클로저의 참조가 그대로 살아 있습니다.

빠르게 고르기

형식쓸 때초기식이 보는 범위
define최상위 이름이나 이름 있는 프로시저현재 최상위 환경
let서로 독립인 로컬 값바깥 환경
let*앞선 로컬에 의존하는 로컬앞서 만든 각 바인딩
letrec서로 재귀하는 로컬 프로시저먼저 할당된 모든 셀, 이른 읽기는 실패
set!기존 셀 갱신새 바인딩을 만들지 않음

흔한 오해

바인딩되지 않은 이름에 set!을 쓰면 E303입니다. 이때 새 바인딩이 만들어지는 일은 없습니다.

현재 경계

  • 내부 미초기화 센티널은 게스트 값으로 나타낼 수 없습니다.

다음으로

클로저가 이 셀을 어떻게 캡처하는지는 프로시저에서 이어집니다. 같은 규칙을 작은 상태 예제로 보려면 클로저 가이드를 여세요.

프로시저 · 클로저 가이드