대입: set!과 set!-values

대입: set!과 set!-values

set!은 변수의 값을 바꾸는 폼이고, set!-values는 여러 값을 한 번에 여러 변수에 대입하는 폼입니다. 이 둘의 전개(expansion) 규칙과 함께, 변환 트랜스포머(transformer)와 함께 쓰일 때의 동작을 설명합니다.

출처: Racket Reference

본문

대입(Assignment)에 대한 소개는 Racket Guide의 set! 문서를 참고하세요.

syntax

(set! id expr)

idmake-set!-transformer로 만들어진 대입 트랜스포머(assignment transformer)에 바인딩되어 있거나, prop:set!-transformer 속성(property)을 가진 구조체 타입의 인스턴스라면, 이 폼은 전체 표현식과 함께 대입 트랜스포머를 호출해 전개됩니다. idmake-rename-transformer로 만들어진 이름 바꾸기 트랜스포머(rename transformer)에 바인딩되어 있거나, prop:rename-transformer 속성을 가진 구조체 타입의 인스턴스라면, 이 폼은 id를 대상 식별자(예: make-rename-transformer에 넘겨진 것)로 바꿔서 전개됩니다. 만약 트랜스포머 바인딩이 prop:set!-transformerprop:rename-transformer 속성을 모두 갖고 있다면, 후자가 우선합니다.

그 외의 경우, expr을 평가하고 그 결과를 id의 위치에 설치합니다. id는 지역 변수로 바인딩되어 있거나, 최상위 변수 또는 모듈 수준 변수로 정의되어 있어야 합니다. id가 가져온(imported) 바인딩을 가리키면 문법 오류가 보고됩니다. id가 아직 정의되지 않은 최상위 변수를 가리키면 exn:fail:contract 예외가 발생합니다.

compile-allow-set!-undefined도 함께 보세요.

예시:

> (define x 12)
> (set! x (add1 x))
> x

13
> (let ([x 5])
    (set! x (add1 x))
    x)

6
> (set! i-am-not-defined 10)

set!: assignment disallowed;

 cannot set variable before its definition

  variable: i-am-not-defined

  in module: top-level

syntax

(set!-values (id ...) expr)

모든 id가 변수를 가리킨다고 가정할 때, 이 폼은 expr을 평가하며, expr은 제공된 id 개수만큼의 값을 만들어내야 합니다. expr에서 나온 각 값은 set!과 같은 방식으로 해당 id의 위치에 채워집니다.

예시:

> (let ([a 1]
        [b 2])
    (set!-values (a b) (values b a))
    (list a b))

'(2 1)

더 일반적으로, set!-values 폼은 다음으로 전개됩니다.

(let-values ([(tmp-id ...) expr])
  (set! id tmp-id) ...)

만약 어떤 id가 대입 트랜스포머에 트랜스포머 바인딩을 갖고 있다면, 이 전개는 추가 전개를 촉발합니다.

더 알아보기

  • Racket Guide의 대입(Assignment) 문서
  • make-set!-transformer, make-rename-transformer 관련 문서
  • compile-allow-set!-undefined 관련 문서