순차 실행: begin, begin0, begin-for-syntax

순차 실행: begin, begin0, begin-for-syntax

여러 표현식을 차례로 실행하고 싶을 때 begin 계열의 폼을 사용해요. 이 문서에서는 순차 실행을 위한 begin, 첫 번째 결과를 돌려주는 begin0, 그리고 문법(syntax) 처리 시점에 실행되는 begin-for-syntax를 설명할게요.

출처: Racket Reference

본문

3.15 순차 실행: begin, begin0, begin-for-syntax

The Racket Guide의 순차 실행 문서에서 beginbegin0을 소개하고 있어요.

(begin form ...)

(begin expr ...+)

첫 번째 형태는 begin이 최상위, 모듈 수준, 또는 내부 정의(internal-definition) 위치에 나타날 때 적용됩니다. 이 경우 begin 폼은 그 안의 폼들을 둘러싼 문맥에 접합(splicing)하는 것과 같습니다.

두 번째 형태는 begin이 표현식 위치에 있을 때 적용됩니다. 이 경우 expr들은 순서대로 평가되고, 마지막 expr을 제외한 결과들은 모두 무시됩니다. 마지막 exprbegin 폼에 대해 꼬리 위치(tail position)에 있어요.

예시:

> (begin
    (define x 10)
    x)
10

> (+ 1 (begin
         (printf "hi\n")
         2))
hi
3

> (let-values ([(x y) (begin
                        (values 1 2 3)
                        (values 1 2))])
   (list x y))
'(1 2)
(begin0 expr ...+)

첫 번째 expr을 평가하고, 그 다음 나머지 expr들을 순서대로 평가하면서 그 결과는 무시합니다. 첫 번째 expr의 결과가 곧 begin0 폼의 결과입니다. 첫 번째 expr은 다른 expr이 없을 때만 꼬리 위치에 있어요.

예시:

> (begin0
    (values 1 2)
    (printf "hi\n"))
hi
1
2

begin-for-syntax 폼

(begin-for-syntax form ...)

최상위 문맥이나 모듈 문맥에서만 허용되며, 각 form의 위상(phase) 수준을 하나씩 올립니다:

  • 표현식은 begin-for-syntax 폼의 문맥보다 한 단계 높은 위상 수준의 바인딩을 참조합니다;

  • define, define-values, define-syntax, define-syntaxes 폼은 begin-for-syntax 폼의 문맥보다 한 단계 높은 위상 수준에서 바인딩합니다;

  • requireprovide 폼 안에서는 기본 위상 수준이 더 높아지는데, 이는 대략 require 폼의 내용을 for-syntax로 감싼 것과 같습니다;

  • 표현식 폼 expr: (define-values-for-syntax () (begin expr (values)))로 변환되는데, 이는 확장 시간에 그 표현식을 효과적으로 평가하고, 모듈 문맥의 경우 그 표현식을 모듈의 향후 방문(visits)을 위해 보존합니다.

모듈 문맥 안에서 begin-for-syntax의 확장 순서와 부분 확장에 대해서는 module을 참고하세요. begin-for-syntax 안의 expr 평가는 let-syntax에서처럼 current-namespace를 설정하도록 매개변수화됩니다.

더 알아보기