pprint-logical-block — 논리 블록으로 출력 묶기
pprint-logical-block — 논리 블록으로 출력 묶기
복잡한 구조를 이쁘게 출력하려면, 어떤 출력이 하나의 '블록'을 이루는지 컴파일러에게 알려줘야 해요. pprint-logical-block은 매크로로, 출력을 논리 블록으로 묶어서 들여쓰기와 줄바꿈을 스스로 처리하게 해줘요.
시그니처
pprint-logical-block (stream-symbol object &key prefix per-line-prefix suffix) declaration* form*
=> nil
본문
인자와 값
stream-symbol— 스트림 변수 지정자(stream variable designator) 예요.object— 객체이고, 평가돼요.:prefix— 문자열이고, 평가돼요. 기본값 결정이 복잡하니 아래 설명을 보세요.:per-line-prefix— 문자열이고, 평가돼요. 기본값 결정이 복잡해요.:suffix— 문자열이고, 평가돼요. 기본값은 빈 문자열(null string) 이에요.declaration—declare표현식이고, 평가되지 않아요.forms— 암묵적 progn이에요.
설명
출력이 논리 블록으로 묶이도록 만들어요.
논리 블록은 stream-symbol이 가리키는 변수의 값인 스트림으로 출력돼요. forms 실행 동안 그 변수는, 출력 배치에 대한 결정을 지원한 뒤 목적지 스트림으로 출력을 전달하는 예쁜 출력 스트림(pretty printing stream) 에 묶여요. 모든 표준 출력 함수(예: write, princ, terpri)로 이 예쁜 출력 스트림에 출력할 수 있어요. 이 예쁜 출력 스트림으로 보내진 출력만, 오직 그것만이 논리 블록 안에 있는 것으로 취급돼요.
prefix는 논리 블록 시작 전에 출력할 접두사를, per-line-prefix는 블록 앞과 블록 안의 각 새 줄 시작 부분에 출력할 접두사를 지정해요. :prefix와 :per-line-prefix 인자는 서로 배타적이에요. 둘 다 지정하지 않으면 빈 문자열의 prefix가 가정돼요.
suffix는 논리 블록 바로 뒤에 출력할 접미사를 지정해요.
object는 보통 몸통 forms가 출력을 담당하는 리스트예요. object가 리스트가 아니면 write로 출력돼요. (잘못된 인자를 만나도 튼튼한 출력 함수를 쉽게 쓸 수 있게 해주죠.) print-circle가 non-nil이고 object가 cons에 대한 순환(또는 공유) 참조라면 적절한 #``n``# 표식이 출력돼요. (순환·공유 축약을 완전히 지원하는 출력 함수를 쉽게 쓸 수 있게 해줘요.) print-level이 nil이 아니고 논리 블록이 논리 블록의 동적 중첩 깊이가 print-level보다 깊다면 #'`'이 출력돼요. (깊이 축약을 완전히 지원하는 출력 함수를 쉽게 쓸 수 있게 해주죠.)
위 세 조건 중 하나라도 발생하면, 표시된 출력이 stream-symbol로 출력되고 몸통 forms는 :prefix·:suffix 출력과 함께 건너뛰어져요. (몸통 forms가 리스트 출력을 담당하지 않는 경우라면 object 인자에 nil을 주어 앞의 두 검사를 끌 수 있어요.)
pprint-logical-block의 object 인자 외에도, 표준 출력 함수(예: write, print, prin1, pprint 및 표준 format 지시자 ~A, ~S(와 ~W)의 인자)들은 모두 (필요할 때) 순환과 공유에 대해 검사돼요. 다만 write-line, write-string, write-char 함수의 인자나 format이 내보내는 리터럴 텍스트에는 그런 검사가 적용되지 않아요. 그 결과, 순환이나 공유 검사를 받지 않아야 하는 리터럴 텍스트를 출력하고 싶다면 반드시 후자의 함수들을 써야 해요.
pprint-logical-block 폼의 몸통 forms는 주변 환경에 어떤 부수 효과(side-effect)도 일으키면 안 돼요. 예를 들어 그 스코프 안에서 묶이지 않은 변수에 값을 할당하면 안 돼요.
이 매크로는 print-pretty의 값과 무관하게 사용할 수 있어요.
예제
없음.
Side Effects
없음.
Affected By
print-circle, print-level.
Exceptional Situations
:suffix, :prefix, :per-line-prefix 중 하나라도 제공됐는데 문자열로 평가되지 않으면 type-error 유형의 오류가 신호돼요.
또한 :prefix와 :per-line-prefix를 둘 다 쓰면 오류가 신호돼요.
pprint-logical-block과 그것이 만드는 예쁜 출력 스트림은 동적 범위(dynamic extent) 를 가져요. 이 범위 밖에서 그 예쁜 출력 스트림으로 출력을 시도하면 결과는 정의되지 않아요. 또한 이 범위 안에서 목적지의 기본 스트림에 직접 출력을 보내면 어떻게 될지는 명시되지 않아요.
Notes
print-pretty의 값이 nil일 때도 이 매크로를 쓰는 이유 중 하나는, dotted list 검사와 (pprint-pop과 함께) print-level·print-length 초과 검사를 수행하게 하기 위함이에요.
순환·공유 검출은 예쁜 프린터가 본질적으로 요청된 출력을 두 번 수행함으로써 지원돼요. 첫 번째 패스에서 순환과 공유가 검출되고 문자 출력은 억제돼요. 두 번째 패스에서 적절한 #``n``=''와 #``n``#'' 표식이 삽입되고 문자가 출력돼요. 그래서 부수 효과 제약이 필요한 거예요. 이 제약을 지키기 쉽게 하려면, 몸통 forms가 출력하는 리스트를 순회할 때 ordinary pop대신pprint-pop`을 쓰면 돼요.
더 알아보기
pprint-pop— 논리 블록에서 요소 꺼내기pprint-exit-if-list-exhausted— 리스트 소진 검사- Section 22.3.5.2 (Tilde Less-Than-Sign: Logical Block)