문서도 또한 dogfood였다

언어 코어가 forcing pain을 낳지 않게 된 뒤, 작업은 언어를 더 capable하게 하는 것에서, legible하게 하는 것으로 옮겨 갔다 —— 왜냐하면 아무도 찾지 못하는 feature는 존재하지 않는 feature이고, 작자 자신이 자기 구문을 놓쳤기 때문이다. 첫 성과물은 언어 전체를 한눈에 보여주는 Tour였다. 하지만 더 깊은 한 수는, 문서 사이트가 언어 자신의 static site generator로 세워져 있다는 것 —— 그래서 docs를 쓰는 것이 그것을 낳은 도구의 dogfood가 되고, 그 dogfood가 실의 빠진 구문을 surface했다 —— 가능한 한 작은 한 바퀴로 루프를 닫으며.

meredocumentationdogfoodssglanguage-design

언어를 더 capable하게 하는 것이 최고 가치의 작업이 아니게 되는 지점이 온다. 앞 Part의 probe가 바로 그 평결에 다다랐다: 코어는 성숙했고, 더 파도 변경을 강요할 만큼 날카로운 아픔은 나오지 않았다. 그래서 무게 중심이 옮겨 갔다 —— 언어를 세우는 것에서, 그것을 쓸 수 있고 읽을 수 있게 하는 것으로. 이행의 계기는 조금 겸연쩍었다. 연재의 앞쪽에서, 작자는 어떤 언어 feature에 손을 뻗었다가, 한순간 그것이 존재함을 잊었다 —— 자기 자신의 list 리터럴 구문을 놓쳤다 —— 그것은 실의 원칙의, 작고 정직한 실연이다: 찾을 수 없는 feature는, 실용상 모든 점에서, 거기 없는 feature다. 다음 일은 발견성이었고, 그 첫 성과물은 tour였다.

검증된 tour

레퍼런스 문서는 이미 철저했고, 튜토리얼은 이미 세심했지만, 그 어느 쪽도 새내기에게 언어 전체를 빠르게 보여주지 않았다. 레퍼런스는 설계상 망라적이다; 튜토리얼은 절차의 이어짐이다. 빠져 있던 것은 Go 커뮤니티가 익숙하게 만든 형태 —— 모든 것을 한 번에 보여주는 한 페이지, 각 feature를 그것을 실연하는 최소의 예로. 그래서 tour가 쓰였다: 식과 curried 함수, 상호 재귀, 대수적 데이터 타입과 매칭, record, list 리터럴과 내포와 패턴, tuple, 문자열과 보간, 앞 Part로부터의 구조적 그림과 JSON과 등가, module과 import, capability effect —— 언어를 한눈에, 그리고 페이지의 각 예는 무엇 하나 소망이 아니도록 먼저 interpreter를 통해 돌렸다. tour는 필요로 하기에 이상한 문서다, 왜냐하면 결심한 독자가 레퍼런스에서 조립할 수 없는 것은 아무것도 가르치지 않기에. 하지만 그것은, 배울 수 있는 언어와 보이는 언어의 차이이고, 보임이 먼저 온다.

언어 자신의 도구로 docs를 쓴다

이 Part를 집안일 이상으로 만든 한 수는, 문서 사이트가 기성 도구로 세워지지 않았다는 것이다. 그것은 Mere로 쓰인 static site generator, 언어 자신의 라이브러리 모음의 일부, 로 세워져 있고, Markdown의 디렉터리를 HTML 페이지 무리로 바꾼다. 그래서 문서를 낳는 것은, 피할 길 없이, 그 generator의 dogfood였다 —— docs의 각 페이지가, 그 docs가 기술하는 언어로 쓰인 프로그램을 통해 돈다. 사이트는 curated한 순서를 얻어, 페이지를 알파벳순으로 늘어놓는 게 아니라 섹션으로 그룹화하고, 각 페이지를 파일명이 아니라 실의 타이틀 아래에 보이고, 그리고 —— 시간을 들여 효하는 작은 배려 —— 카탈로그되지 않은 페이지를 자동으로 말미에 덧붙이는 안전망을 얻었다, 그래서 새로 쓰인 문서가 순서에서 잊혀 사이트에서 조용히 사라지는 일은 결코 없다.

도구가, 쓰였을 때 찾은 것

진심으로 쓰이는 것이 도구를 정직하게 하고, generator는 즉시 자기 자신에 대해 보고했다. 몇몇 라이브러리 파일이, import되면 실연 코드를 돌려 표준 출력에 print했다 —— 다른 라이브러리에서 이전에 잡혀 고쳐지고, 이것들에서 조용히 재발한 패턴. import하면 데모를 돌리는 파일은 라이브러리가 아니다; 라이브러리의 옷을 입은 스크립트이고, 그 출력이 사이트 빌드의 도중에 초대받지 않고 나타났다. 그것들은 정의만으로 잘렸다. 더 작은 것: 문자열 보간이 수를 자동으로 그리지 않아, 문자열에 끼워 넣는 값은 명시적으로 텍스트로 바꿀 필요가 있었다. 이것들의 저마다는 리뷰가 아니라 사용에 의해 찾아졌고, 그것이 유일하게 그것들이 찾아질 수 있던 곳이다.

콤마, 그리고 가능한 한 작은 루프

가장 날카로운 발견은 가장 작았다. 사이트 generator 자신의 소스를 쓰는 것이 빠진 구문에 부딪혔다: list나 tuple의 마지막 요소 뒤의 트레일링 콤마 —— 다음 줄을 더하는 것이 한 줄의 변경이 되도록 남겨 두는 콤마 —— 가 parser에 거부되었다. papercut이지만, 실의 코드를 쓰는 사람이 끊임없이 마주치는 종류의 papercut 이고, 실의 코드가 쓰일 때까지 보이지 않았다. parser는 그것을 받아들이도록 가르쳐졌고, 그것은 두 갈래의 변경으로 판명되었고, 그리고 설계가 이미 일관적이었다는 기분 좋은 확인으로, record는 줄곧 트레일링 콤마를 받아들이고 있었다. 이것은 dogfood 루프의 가장 팽팽한 것: 프로그램이 쓰이고, 그 씀이 마찰에 만나고, 마찰이 언어 안의 수정이 되고, 수정이 ship한다 —— 다만 여기서 쓰이던 프로그램은 문서 사이트였고, 한 바퀴 통째가 거의 한 번에 닫혔다. 루프는 웅장한 애플리케이션을 요하지 않는다. 언어에 대해, 언어로 쓰는 것이, 그것을 개선하기에 충분했다.

자기 자신의 현관

마지막 한 조각은 기술적이지 않았지만 중요했다: 사이트가 자기 자신의 이름으로, 호스트의 공유 주소 아래의 프로젝트 경로가 아니라 제대로 된 도메인으로 옮겼고, 옛 주소가 새것으로 리다이렉트하고, 그래서 기존의 링크는 하나도 깨지지 않는다. 빌드는 대화적인 playground 페이지를 각 배포의 일부로 재생성하므로, 브라우저 속의 컴파일러의 데모가 컴파일러 자신과 보조를 맞춰 나간다. 존재 통째를 내부 프로젝트로 지내 온 언어가, 이제 현관을 가졌다 —— 방문자를 먼저 tour로 향하게 하는 landing 페이지, 의도된 순서의 문서 모음, 그리고 실제로 소리 내어 말할 수 있는 주소.

이 어느 것도 언어를 더 강력하게 하지 않았다, 그리고 그것이 요점이었다. 그것은 언어를 닿게 했다, 그것은 다른 축이고, 이 단계에서는, 더 값진 축이다. 그리고 그렇게 한 것은, 그 이전의 모든 것과 같은 규율 안에 머물면서: docs는 언어 자신의 도구로 세워졌으므로, docs를 개선하는 것과 언어를 개선하는 것이 같은 활동임이 판명되었다, 하나의 루프, 한 번에 하나의 콤마로 닫히는.

← Back to Mere: 언어를 만들다