Hy の macroexpand が S 式じゃない→直した
Python
へ直接コンパイルできる Lisp 方言 Hy が楽しいです。 しかし Lisp 族のつもりでいると思わぬ落とし穴があったり( let
, cons
がないなど)するので、 とりあえず macroexpand
の結果を S 式にしてみます。
例えば let
をマクロで定義してみましょう。 let
の正体は lambda
というか関数なので、 無名関数を使って実装します。
(defmacro let [values &rest body] (setv var-names (list (map first values)) var-vals (list (map second values))) `((fn [~@var-names] ~@body) ~@var-vals))
デフォルトの macroexpand-1
の挙動はこんな感じ。
=> (macroexpand-1 '(let ((var 1)) (print var))) HyExpression([ HyExpression([ HySymbol('fn'), HyList([ HySymbol('var')]), HyExpression([ HySymbol('print'), HySymbol('var')])]), HyInteger(1)])
待って読めない。
もうちょっと Lisper 向けの表現(= S-expression)に近づけてほしいので、 hy
コマンドを起動するときに引数をつけてあげます。
hy --repl-output-fn=hy.contrib.hy-repr.hy-repr
これで macroexpand
してみると、今度はこんな感じに。
=> (macroexpand-1 '(let ((var 1)) (print var))) '((fn [var] (print var)) 1)
なぜか一行で表示されましたが、それでもこちらのほうが何倍も読みやすいです。
私は Emacs 使いなので hy-mode
経由で hy
シェルを起動しているんですが、その場合は hy-shell-interpreter-args
(デフォルト "--spy"
)を変更すればよい感じです。
(add-hook 'hy-mode-hook (lambda () (setq hy-shell-interpreter-args (concat "--repl-output-fn=hy.contrib.hy-repr.hy-repr " hy-shell-interpreter-args))))
Hy
がもっと繁栄しますように。