pprint-logical-block — 논리 블록으로 출력 묶기

pprint-logical-block — 논리 블록으로 출력 묶기

복잡한 구조를 이쁘게 출력하려면, 어떤 출력이 하나의 '블록'을 이루는지 컴파일러에게 알려줘야 해요. pprint-logical-block매크로로, 출력을 논리 블록으로 묶어서 들여쓰기와 줄바꿈을 스스로 처리하게 해줘요.

출처: PPRINT-LOGICAL-BLOCK - Common Lisp HyperSpec

시그니처

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) 이에요.
  • declarationdeclare 표현식이고, 평가되지 않아요.
  • 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-circlenon-nil이고 objectcons에 대한 순환(또는 공유) 참조라면 적절한 #``n``# 표식이 출력돼요. (순환·공유 축약을 완전히 지원하는 출력 함수를 쉽게 쓸 수 있게 해줘요.) print-level이 nil이 아니고 논리 블록이 논리 블록의 동적 중첩 깊이print-level보다 깊다면 #'`'이 출력돼요. (깊이 축약을 완전히 지원하는 출력 함수를 쉽게 쓸 수 있게 해주죠.)

위 세 조건 중 하나라도 발생하면, 표시된 출력이 stream-symbol로 출력되고 몸통 forms:prefix·:suffix 출력과 함께 건너뛰어져요. (몸통 forms가 리스트 출력을 담당하지 않는 경우라면 object 인자에 nil을 주어 앞의 두 검사를 끌 수 있어요.)

pprint-logical-blockobject 인자 외에도, 표준 출력 함수(예: 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-prettynil일 때도 이 매크로를 쓰는 이유 중 하나는, 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)