Clojureでの 文芸的プログラミング(Literate Programming) の可能性を検討した.
というのもnreplやdesign journalのことを調べるうちに, 文芸的プログラミングと相性がいいんじゃないかなと考えた.
前置き: Clojure と org-babelの探求のモチベーション
実は過去にEmacs org-babalを活用していろいろと取り組んでいたことがある.
- 🔗org-babel と R の組み合わせがとても心地よい件 | Futurismo
- 🔗coursera で Reproducible Research をうけた | Futurismo
- 🔗散文的ブログラミングの哲学につら抜かれたCleanCodeでカルチャーショック体験 | Futurismo
ただこれらの取り組みは2015年ごろ. そのあと2016年くらいからAIブームが到来して, Jupyter Notebookの登場によって 文芸的プログラミングという言葉は流行らなかったが, その手法はメジャーになった.
わたしもプログラミングからすこし離れていたが, 最近再びClojureとEmacsを触り始め, 昔を懐かしく思う気持ちからEmacsとorg-modeをいじり始めた. その延長でorg-babelとClojureを使った文芸的プログラミングの可能性を探り始めたわけだ.
REPL駆動開発とDesign Journalについて
Clojureのことを調べていると Design Journalという方法を知った.
ソースは Practical.liサイトのREPL Driven Developmentの紹介 から.
REPL駆動開発でコードを書くと,まずごにょごにょとアイデアを文で書いたりそれを小さな関数で実装して評価してみたりを繰り返しながら,つまりエディタと対話しながら小さな部品を組み立てていき,それらを組み合わせて大きな機能をつくる.
ref: 🖊REPL 駆動開発について(REPL Driven Development) 調べたメモ | Futurismo
そのごにょごにょの部分はソースコードの下のほうにコメントアウトしつつ残しておくことで,どういう設計意図があってこのコードを実装したのかの履歴を,コードとともに残しておこうという考え.
こういうことができるのは,REPLで関数をかんたんに評価できるということもあるが,別の側面としてはClojureが関数型言語なので簡潔に副作用もなく部品としてコードを残しやすいという側面がある(と個人的には思っている).
実際にClojureで実施するときは comment マクロをつかうとまとめてコメントアウトできる.
Emacs Ciderだと, 式の評価結果をそのまま次の行に出力すると後で思い出すときにいちいち評価しなくてもいい.
- M-x cider-pprint-eval-defun-to-comment
- M-x cider-pprint-eval-last-sexp-to-comment
この方法のよいところは, 試行錯誤してコードを書いた履歴がそのままコードの下部に残るため, あとから見直したときに情報を拾えるというものがある. また簡単なデバッグ用スニペットも同様に残すことができる.
もっとも雑然とした情報は将来の自分の時間を奪うことにもつながるので, 整理して残さないとゴミになるが.
ただ, 最近のわたしのメモの方法としては org-journal にいろいろ書き込んでいることもあり, どうせ叩いたコマンドやら試行錯誤メモは org-journalにも書くので, org-journalからコードが実行できれば最高だと思った.
そこで, org-babelである.
org-babel からnREPL経由でClojureをつかう
org-babelはEmacs org-mode上に書いたコードをその場で実行して結果もメモに出力できる.
具体的にはorg-modeからcider-jack-inでREPLに乗り込むのだ.
Clojure開発で優れている点は, nREPL という REPLにリモート接続する機能で, org-modeから直接REPLを操作してその評価結果がorg-modeに残せるところ.
もちろんorg-babelにはsessionのようなスクリプト言語において codeの情報を共有する仕組みは元からあるが, ClojureのREPLへ接続するようなことは別のよいアプローチでありREPLの長所.
org-modeの具体的な設定方法は以下.
- begin_src clojureを指定してorg-babelにclojureを設定.
- :results ppをすることで結果をpretty print
- valueという評価結果を表示する指定はdefaultのため省略されている.
- :ns fooを宣言すると, 起動時のnamespaceを設定できる.
- resultは指定した nsにbindされる.
#+begin_src clojure :results pp
(require '[lib.twitter.guest :as guest])
(guest/get-user "richhickey")
#+end_src
コードの実行方法は, まず事前にREPLを立ち上げておき, C-c C-c を実行することでコードを評価. cider-jack-in or cider-connectの選択を求められる. 事前に立ち上げておいたREPLにcider-connect
org-modeとrestclientの連携もよい
同様にして org-modeからrestを叩くrestclient.elも良かったので紹介しておく.
pashky/restclient.el: HTTP REST client tool for emacs
これはEmacs上でコードをインタラクティブに評価することで HTTP Requestを発行するようなクライアントだが, ob-restclientをつかいorg-babelと連携させることで化ける.
https://github.com/alf/ob-restclient.el
Jupyter Notebookと探索的プログラミングと自由という思想
文芸的プログラミングというのはもはやJupyter Notebookが天下を取ったのかもしれない. さらにいえばGooge Colabかな? 実際にJupyter NotebookでClojureを走らせる試みもある. もはや, Emacsを持ち出して文芸的プログラミングをやりだすとは昭和生まれならではの発想だ.
しかし, である.
わたしがClojureをやりだした元々の原因はEmacsをさわりたかったからであり, 仕事でJavaをつかうようになって泣く泣くEmacsから離れた過去を償うためであり, もうどんなに化石野郎になってもEmacsを鍛え上げようという決意がある.
そうするとやはりJupyter Notebookには魅力を感じつつ, Emacsに拘るという点でこのorg-babelのハックは意義がある.
もちろんJupyter Notebook上でClojureを動かすことも興味があるのでいずれ取り組みたい.
RDDにしろJupyter Notebookにしろ, 試行錯誤しながらプログラミングすることは探索的プログラミングという(Exploratry Programming).
わたしはこういうプログラミングスタイルは大好きだ. 逆に言えば嫌いなものは静的型付. そしてこれ支える価値観は, わたしは自由が好きだということだ.
自由でありたいというわたしの価値観を, プログラミング言語と結びつける.