예쁜 출력

예쁜 출력 (Pretty Printing)

racket/pretty 라이브러리는 값을 보기 좋게 줄 바꿈과 들여쓰기를 넣어 출력하는 pretty-print 계열 함수와, 동작을 조정하는 여러 파라미터를 제공해요. 긴 표현식을 읽기 좋게 출력하고 싶을 때 유용해요.

출처: Racket Reference

본문

13.6 예쁜 출력

(require racket/pretty) package: base

이 절에서 문서화한 바인딩은 racket/prettyracket 라이브러리가 제공하지만, racket/base는 제공하지 않아요.

procedure

(pretty-print v
              [port
               quote-depth
               #:newline? newline?]) → void?
  v : any/c
  port : output-port? = (current-output-port)
  quote-depth : (or/c 0 1) = 0
  newline? : boolean? = #t

v를 기본 print 모드와 같은 출력 형태로 예쁘게 출력하되, (pretty-print-columns)로 제어되는 (pretty-print-current-style-table)에 따라 (pretty-print-columns)보다 긴 줄이 생기지 않도록 줄 바꿈과 공백을 넣어요. 출력 형태는 기본적으로 줄 바꿈으로 끝나는데, newline? 인자에 false를 주거나 pretty-print-columns 파라미터가 'infinity로 설정된 경우에는 예외예요. port가 줄 세기(행·열 세기(Counting Positions, Lines, and Columns) 참고)를 활성화하면, 출력이 시작될 때의 열에 민감해져요—초기 줄 바꿈 결정과 이후 줄 들여쓰기 모두에 영향을 줘요.

이 절에서 정의된 파라미터 외에도 pretty-printprint-graph, print-struct, print-hash-table, print-vector-length, print-box, print-as-expression 파라미터를 따릅니다.

예쁜 출력기는 prop:custom-write 속성을 가진 구조체를 감지하고 해당 custom-write 프로시저를 호출해요. custom-write 프로시저는 pretty-printing 파라미터를 확인해 예쁜 출력기와 협력할 수 있어요. 포트로의 재귀 출력은 자동으로 예쁜 출력을 사용하지만, 구조체에 재귀적으로 출력되는 하위 표현식이 여러 개 있다면 custom-write 프로시저가 명시적 줄 바꿈을 넣기 위해 더 협력해야 할 수 있어요. 현재 출력 열을 알아보려면 port-next-location을, 대상 출력 너비를 정하려면 pretty-print-columns를, 줄 바꿈을 넣으려면 pretty-print-newline을 사용해요(pretty-print-print-line 파라미터의 함수가 적절히 호출되도록). 잠정적(tentative) 재귀 출력(예: 출력 길이 확인)을 위한 포트를 얻으려면 make-tentative-pretty-print-output-port를 사용해요.

newline? 인자를 생략하거나 true로 주면, 출력된 값 뒤의 마지막 줄 바꿈을 출력하기 위해 pretty-print-print-line 콜백이 첫 번째 인자로 false를 받아 호출돼요. false로 주면 출력된 값 뒤에서는 pretty-print-print-line 콜백이 호출되지 않아요.

package base 6.6.0.3에서 변경: newline? 인자 추가.

procedure

(pretty-write v [port #:newline? newline?]) → void?
  v : any/c
  port : output-port? = (current-output-port)
  newline? : boolean? = #t

pretty-print와 같지만, vprint가 아닌 write처럼 출력해요.

package base 6.6.0.3에서 변경: newline? 인자 추가.

procedure

(pretty-display v [port #:newline? newline?]) → void?
  v : any/c
  port : output-port? = (current-output-port)
  newline? : boolean? = #t

pretty-print와 같지만, vprint가 아닌 display처럼 출력해요.

package base 6.6.0.3에서 변경: newline? 인자 추가.

procedure

(pretty-format v [columns #:mode mode]) → string?
  v : any/c
  columns : exact-nonnegative-integer? = (pretty-print-columns)
  mode : (or/c 'print 'write 'display) = 'print

pretty-print와 비슷하지만, 출력을 포트로 보내는 대신 예쁘게 출력된 값을 담은 문자열을 반환해요.

선택적 columns 인자는 pretty-print-columns를 파라미터화하는 데 사용돼요.

키워드 인자 mode는 출력을 pretty-print(기본값), pretty-write, pretty-display 중 어떤 식으로 할지 제어해요.

package base 6.3에서 변경: mode 인자 추가.

procedure

(pretty-print-handler v) → void?
  v : any/c

v#<void>가 아니면 v를 예쁘게 출력하고, v#<void>이면 아무 것도 출력하지 않아요. 이 프로시저를 current-print에 전달하면 read-eval-print-loop가 실행하는 REPL에 예쁜 출력기를 설치할 수 있어요.

13.6.1 기본 예쁜 출력 옵션

parameter

(pretty-print-columns) → (or/c exact-positive-integer? 'infinity)
(pretty-print-columns width) → void?
  width : (or/c exact-positive-integer? 'infinity)

예쁜 출력의 기본 너비를 결정하는 파라미터예요.

표시 너비가 'infinity이면 예쁜 출력된 결과가 절대 줄 바꿈되지 않고, 출력 끝에 줄 바꿈도 추가되지 않아요.

parameter

(pretty-print-depth) → (or/c exact-nonnegative-integer? #f)
(pretty-print-depth depth) → void?
  depth : (or/c exact-nonnegative-integer? #f)

재귀 예쁜 출력의 기본 깊이를 제어하는 파라미터예요. depth까지 출력한다는 것은 depth보다 깊게 중첩된 원소가 "..."으로 대체된다는 뜻이에요. 특히 깊이 0은 단순한 값만 출력된다는 뜻이에요. #f(기본값) 깊이는 임의 깊이까지 출력을 허용해요.

parameter

(pretty-print-exact-as-decimal) → boolean?
(pretty-print-exact-as-decimal as-decimal?) → void?
  as-decimal? : any/c

정확한(exact) 비정수(분수)를 어떻게 출력할지 결정하는 파라미터예요. 값이 #t이면 소수 표현이 가능한 정확한 비정수를 분수 대신 십진수로 출력해요. 초기값은 #f예요.

parameter

(pretty-print-.-symbol-without-bars) → boolean?
(pretty-print-.-symbol-without-bars on?) → void?
  on? : any/c

출력 이름이 그냥 마침표(period)인 심볼의 출력을 제어하는 파라미터예요. 참 값으로 설정하면 그런 심볼을 마침표 하나로만 출력해요. 거짓 값으로 설정하면 주변에 세로 막대(vertical bar)를 두른 마침표로 출력해요.

parameter

(pretty-print-show-inexactness) → boolean?
(pretty-print-show-inexactness show?) → void?
  show? : any/c

부정확(inexact) 숫자를 어떻게 출력할지 결정하는 파라미터예요. 값이 #t이면 부정확 숫자가 항상 앞에 #i를 붙여 출력돼요. 초기값은 #f예요.

13.6.2 심볼별 특수 출력

parameter

(pretty-print-abbreviate-read-macros) → boolean?
(pretty-print-abbreviate-read-macros abbrev?) → void?
  abbrev? : any/c

quote, unquote, unquote-splicing 등을 ', ,, ,@ 등으로 줄여 쓸지 여부를 제어하는 파라미터예요. 기본적으로 줄임 표기는 활성화되어 있어요.

pretty-print-remap-stylable도 함께 보세요.

procedure

(pretty-print-style-table? v) → boolean?
  v : any/c

vpretty-print-current-style-table과 함께 쓰는 스타일 테이블이면 #t를, 그렇지 않으면 #f를 반환해요.

parameter

(pretty-print-current-style-table) → pretty-print-style-table?
(pretty-print-current-style-table style-table) → void?
  style-table : pretty-print-style-table?

스타일 매핑 테이블을 담는 파라미터예요. pretty-print-extend-style-table을 보세요.

procedure

(pretty-print-extend-style-table style-table
                                 symbol-list
                                 like-symbol-list)
  → pretty-print-style-table?
  style-table : pretty-print-style-table?
  symbol-list : (listof symbol?)
  like-symbol-list : (listof symbol?)

기존 style-table을 확장해 새 스타일 테이블을 만들어요. 원본 테이블에서 like-symbol-list의 각 심볼에 대한 스타일 매핑이 새 테이블에서 symbol-list의 대응 심볼에 사용돼요. symbol-listlike-symbol-list 리스트는 길이가 같아야 해요. style-table 인자는 #f일 수 있는데, 이 경우 원본 테이블의 기본 매핑이 사용돼요(아래 참조).

심볼에 대한 스타일 매핑은 그 심볼로 시작하는 리스트를 출력할 때 공백을 어떻게 넣을지를 제어해요. 매핑이 없으면 리스트가 여러 줄로 나뉠 때 각 원소가 각자 같은 들여쓰기로 자기 줄에 출력돼요.

기본 스타일 매핑에는 다음 심볼에 대한 매핑이 포함되어 있어, 출력이 널리 쓰이는 코드 형식 규칙을 따르게 해요.

'lambda 'λ 'case-lambda
'define 'define-macro 'define-syntax
'let 'letrec 'let*
'let-syntax 'letrec-syntax
'let-values 'letrec-values 'let*-values
'let-syntaxes 'letrec-syntaxes
'begin 'begin0 'do
'if 'set! 'set!-values
'unless 'when
'cond 'case 'and 'or
'module
'syntax-rules 'syntax-case 'letrec-syntaxes+values
'import 'export 'link
'require 'require-for-syntax 'require-for-template 'provide
'public 'private 'override 'rename 'inherit 'field 'init
'shared 'send 'class 'instantiate 'make-object

parameter

(pretty-print-remap-stylable) → (any/c . -> . (or/c symbol? #f))
(pretty-print-remap-stylable proc) → void?
  proc : (any/c . -> . (or/c symbol? #f))

스타일 및 리더 줄임 표기 결정에 대한 재매핑을 제어하는 파라미터예요.

이 프로시저는 수열에서 첫 번째 원소로 나타나는 각 하위 표현식마다 호출돼요. 심볼을 반환하면 스타일 테이블이 마치 그 심볼이 수열의 머리에 있는 것처럼 사용돼요. #f를 반환하면 스타일 테이블이 정상적으로 취급돼요. 마찬가지로 리더 매크로를 줄여 쓸지 결정할 때도 이 파라미터를 참고해요.

13.6.3 줄 출력 훅

procedure

(pretty-print-newline port width) → void?
  port : output-port?
  width : exact-nonnegative-integer?

port가 인쇄용으로 원본 출력 포트로 리다이렉트되는 출력 포트라면 pretty-print-print-line 파라미터와 연결된 프로시저를 호출해 port에 줄 바꿈을 출력하고, 그렇지 않으면 port에 평범한 줄 바꿈을 출력해요. width 인자는 대상 열 너비여야 하며, 보통 pretty-print-columns에서 얻어요.

((or/c exact-nonnegative-integer? #f)
 output-port?
 exact-nonnegative-integer?
 (or/c exact-nonnegative-integer? 'infinity)
 . -> .
 exact-nonnegative-integer?)

parameter

(pretty-print-print-line) →
((or/c exact-nonnegative-integer? #f)
 output-port?
 exact-nonnegative-integer?
 (or/c exact-nonnegative-integer? 'infinity)
 . -> .
 exact-nonnegative-integer?)

예쁘게 출력된 값의 줄 사이 줄 바꿈 구분자를 출력하는 프로시저를 결정하는 파라미터예요. 프로시저는 네 개의 인자로 호출돼요: 새 줄 번호, 출력 포트, 이전 줄의 길이, 대상 열 수. proc의 반환 값은 새 줄의 시작 부분에 출력한 추가 문자 수예요.

proc 프로시저는 어떤 문자도 출력되기 전에 줄 번호 0과 이전 줄 길이 0으로 호출돼요. 예쁜 출력기가 새 줄을 시작할 때마다 proc는 새 줄의 번호(첫 새 줄은 1로 번호가 매겨짐)와 방금 끝난 줄의 길이로 호출돼요. proc의 대상 열 수 인자는 항상 대상 인쇄 영역의 전체 너비이거나, 예쁘게 출력된 값이 줄로 나뉘지 않으면 'infinity예요.

#:newline? 인자를 생략하거나 참 값을 주면, 값의 마지막 문자가 출력된 뒤에도 proc가 줄 번호 #f와 마지막 줄의 길이로 호출돼요.

기본 proc 프로시저는 줄 번호가 0이 아니고 열 수가 'infinity가 아닐 때마다 줄 바꿈을 출력하며, 항상 0을 반환해요. 사용자 정의 proc 프로시저를 이용해 예쁜 출력의 각 줄 앞에 추가 텍스트를 출력할 수 있어요. 다음 줄 바꿈을 올바르게 선택하려면 각 줄 앞에 출력한 문자 수를 proc가 반환해야 해요.

proc에 제공되는 대상 포트는 일반적으로 pretty-printpretty-display에 주어진 포트(또는 현재 출력 포트)가 아니라, 이 포트로의 출력이 결국 pretty-printpretty-display에 주어진 포트로 리다이렉트돼요.

13.6.4 값 출력 훅

(any/c boolean? output-port?
 . -> .
 (or/c #f exact-nonnegative-integer?))

parameter

(pretty-print-size-hook) →
(any/c boolean? output-port?
 . -> .
 (or/c #f exact-nonnegative-integer?))

예쁜 출력을 위한 크기 훅(sizing hook)을 결정하는 파라미터예요.

크기 훅은 출력할 각 값에 적용돼요. 훅이 #f를 반환하면 출력은 예쁜 출력기에 의해 내부에서 처리돼요. 그렇지 않으면 값은 출력된 값의 길이를 문자 수로 지정하는 정수여야 하며, 실제 출력을 위해 인쇄 훅이 호출돼요(pretty-print-print-hook 참고).

크기 훅은 세 개의 인자를 받아요. 첫 번째 인자는 출력할 값이에요. 두 번째 인자는 불리언으로, #tdisplay처럼 출력, #fwrite처럼 출력을 뜻해요. 세 번째 인자는 대상 포트로, pretty-printpretty-display에 주어진 포트(또는 현재 출력 포트)예요. 크기 훅은 예쁜 출력 중에 하나의 값에 여러 번 적용될 수 있어요.

parameter

(pretty-print-print-hook) → (any/c boolean? output-port? . -> . void?)
(pretty-print-print-hook proc) → void?
  proc : (any/c boolean? output-port? . -> . void?)

예쁜 출력을 위한 인쇄 훅을 결정하는 파라미터예요. 크기 훅(pretty-print-size-hook 참고)이 어떤 값에 대한 정수 크기를 반환하면, 출력을 위해 그 값에 인쇄 훅 프로시저가 적용돼요.

인쇄 훅은 세 개의 인자를 받아요. 첫 번째는 출력할 값이에요. 두 번째는 불리언으로, #tdisplay처럼 출력, #fwrite처럼 출력을 뜻해요. 세 번째는 대상 포트로, 일반적으로 pretty-printpretty-display에 주어진 포트(또는 현재 출력 포트)가 아니지만, 이 포트로의 출력은 결국 pretty-printpretty-display에 주어진 포트로 리다이렉트돼요.

parameter

(pretty-print-pre-print-hook) → (any/c output-port? . -> . void)
(pretty-print-pre-print-hook proc) → void?
  proc : (any/c output-port? . -> . void)

어떤 객체가 출력되기 직전에 호출될 훅 프로시저를 결정하는 파라미터예요. 훅은 객체와 출력 포트 두 인자를 받아요. 포트는 pretty-printpretty-display에 주어진 포트(또는 현재 출력 포트)예요.

parameter

(pretty-print-post-print-hook) → (any/c output-port? . -> . void)
(pretty-print-post-print-hook proc) → void?
  proc : (any/c output-port? . -> . void)

어떤 객체가 출력된 직후에 호출될 훅 프로시저를 결정하는 파라미터예요. 훅은 객체와 출력 포트 두 인자를 받아요. 포트는 pretty-printpretty-display에 주어진 포트(또는 현재 출력 포트)예요.

13.6.5 추가 커스텀 출력 지원

parameter

(pretty-printing) → boolean?
(pretty-printing on?) → void?
  on? : any/c

줄 바꿈을 지원하는 모드로 출력할 때 예쁜 출력기가 custom-write 프로시저(prop:custom-write 참고)를 호출하면 #t로 설정되는 파라미터예요. 예쁜 출력기가 순환을 감지하기 위해서만 custom-write 프로시저를 호출하거나 한 줄로 출력하려고 시도할 때는 이 파라미터를 #f로 설정해요.

procedure

(make-tentative-pretty-print-output-port out
                                        width
                                        overflow-thunk)
  → output-port?
  out : output-port?
  width : exact-nonnegative-integer?
  overflow-thunk : (-> any)

실제로 출력을 만들지 않고 재귀 예쁜 출력에 적합한 출력 포트를 만들어요. 올바른 출력이 재귀 출력의 크기에 의존할 때, 그런 포트를 사용해 잠정적으로 출력해 보세요. 출력 후 file-position으로 잠정 출력의 크기를 알아내요.

out 인자는 예쁜 출력 포트여야 해요. 예를 들어 pretty-printing이 true로 설정될 때 custom-write 프로시저에 주어진 포트나, 다른 잠정 출력 포트가 그 예가 될 수 있어요. width 인자는 대상 열 너비로, 보통 pretty-print-columns에서 얻고 종결자 공간을 남기기 위해 감소시킬 수도 있어요. overflow-thunk 프로시저는 width보다 많은 항목이 포트에 출력되거나 pretty-print-newline으로 포트에 줄 바꿈이 출력되면 호출돼요. 이 프로시저는 연속(continuation)을 통한 지름길로 재귀 출력에서 벗어날 수 있지만, 반환할 수도 있는데 이 경우 이후 포트에 추가 출력이 쓰여질 때마다 호출돼요.

잠정 출력 후에는 tentative-pretty-print-port-transfer로 결과를 받아들이거나 tentative-pretty-print-port-cancel로 거부해요. 제대로 받아들이거나 취소하지 않으면 그래프 구조 출력, 훅 프로시저 호출 등에 문제가 생겨요. overflow-thunk가 재귀 출력에서 벗어난 경우에도 잠정 출력을 명시적으로 취소해요.

procedure

(tentative-pretty-print-port-transfer tentative-out
                                     orig-out) → void?
  tentative-out : output-port?
  orig-out : output-port?

tentative-out에 쓰인 데이터가 orig-out에 쓰인 것처럼 전송되도록 해요. tentative-out 인자는 make-tentative-pretty-print-output-port가 만든 포트여야 하고, orig-out은 예쁜 출력 포트(custom-write 프로시저에 주어진)이거나 또 다른 잠정 출력 포트여야 해요.

procedure

(tentative-pretty-print-port-cancel tentative-out) → void?
  tentative-out : output-port?

make-tentative-pretty-print-output-port가 만든 tentative-out의 내용을 취소해요. 취소의 주된 효과는 그래프 참조 정의를 되돌려, 나중에 그래프 참조 객체를 출력할 때 정의 #`‹n›```=가 포함되게 하는 거예요.

더 알아보기