Inspect.Algebra
Inspect.Algebra
대수 문서(algebra document)를 만들고 조작하는 함수 모음이에요. 이 모듈은 “Strictly Pretty” (2000) by Christian Lindig에 설명된 기능을, 이진(binary) 노드 지원과 수평 공간 사용을 극대화하는 break 모드 같은 약간의 추가와 함께 구현해요.
iex> Inspect.Algebra.line()
:doc_line
iex> "foo"
"foo"
이 모듈의 함수로 서로 다른 요소를 연결하고 렌더링할 수 있어요.
iex> doc = Inspect.Algebra.concat(Inspect.Algebra.empty(), "foo")
iex> Inspect.Algebra.format(doc, 80)
"foo"
nest/2, space/2, line/2 함수는 문서를 단단한 구조로 묶는 데 도움을 줘요. 하지만 문서 대수(document algebra)가 재미있어지는 건 glue/3와 group/1 같은 함수를 쓸 때예요. glue는 두 문서 사이에 break를 넣고, group은 현재 줄에 들어맞아야 하는 문서를 나타내며 안 그러면 break가 새 줄로 렌더링돼요. 두 문서를 break로 붙이고 group한 뒤 렌더링해 볼게요.
iex> doc = Inspect.Algebra.glue("a", " ", "b")
iex> doc = Inspect.Algebra.group(doc)
iex> Inspect.Algebra.format(doc, 80)
"a b"
줄 제한에 도달하지 않았으므로 break가 그대로 표현됐어요. 일단 도달하면 새 줄로 대체돼요.
iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b")
iex> doc = Inspect.Algebra.group(doc)
iex> Inspect.Algebra.format(doc, 10)
"aaaaaaaaaaaaaaaaaaaa
b"
이 모듈은 남은 공간이 얼마나 되는지 계산할 때 바이트 크기를 사용해요. 문서에 문자열이 있으면 string/1로 감싸야 하는데, string/1은 String.length/1에 의존해 문서 크기를 미리 계산해요. 마지막으로 이 모듈에는 Elixir 포맷팅과 관련된 to_doc/2 같은 Elixir 관련 함수도 들어 있어요.
출처: Inspect.Algebra
본문
구현 세부 사항 (Implementation details)
Inspect.Algebra의 구현은 Lindig의 Strictly Pretty 논문에 기반해요. 이 논문은 이전 pretty printing 알고리즘 위에 세워졌지만 Elixir 같은 엄격한(strict) 언어에 맞춰져 있어요. 논문의 핵심 아이디어는 명시적 문서 그룹을 사용하는 거예요. 그룹은 flat(break를 공백으로) 또는 break(break를 새 줄로)로 렌더링돼요.
이 구현은 :strict와 :flex 두 종류의 break를 제공해요. 그룹이 들어맞지 않으면 모든 strict break가 새 줄로 처리돼요. 반면 flex break는 발생할 때마다 다시 평가되어 여전히 flat으로 렌더링될 수 있어요. 자세한 내용은 break/1과 flex_break/1을 참고하세요. 이 구현은 문서 맞춤(fitting)에 더 많은 제어를 주는 force_unfit/1과 낙관적/비관적(optimistic/pessimistic) 그룹도 추가해요.
더 알아보기
- Inspect — 구조체와 자료 구조를 대수 문서로 바꾸는 프로토콜
- Inspect.Opts — inspect 옵션
- “Strictly Pretty” (2000) by Christian Lindig — 이 모듈이 구현하는 원리