要約
Common Lisp のサブセットのインタープリタは(趣味で)何回か作った事のある私が、Schemeのインタープリタを趣味で、作ろうとしたら、大変苦戦中。
Common Lisp も Scheme も同じ Lisp系の言語として、同列に語られがちだが、インタープリタの作り方は、全く異なる。
似て非なる言語である。
Schemeは、あなどられているかも知れない。
Schemeについて、よく聞く噂(都市伝説)として以下のものがある
Schemeの仕様書は50ページしかないので、誰でも簡単に作れる。
一番最初に自作言語作って遊ぶのなら Schemeでしょ。
とんでもなく、間違っていると、私は思う。
Common Lispのインタープリタを何回か作った私でも、頭を抱えて悩むくらいの難しい機能のオンパレードだ。
難しい機能の例
call/cc
これが、Common Lispと、Schemeを区別する一番有名な機能かも知れない。
幸いこれには、日本語で読める大変良い記事があった。
私は、この記事を読んでschemeの自作を始めた。約1ヶ月で、call/ccが動くようになった。
Tail リカージョンの最適化
私はschemeをJavaで作成している。
Clojureを作った、天才のリッチヒッキーさんでさえも、JavaのVMは関数型言語用に設計されていないので、「Clojure(on Java VM)で、Tail リカージョンの最適化をするのは無理」と書かれていた。
衛生的マクロ
define-syntax, syntax-rules という、Common Lispとは違うマクロシステムを搭載している。
これについて、色々検索してみたが、参考になりそうな日本語の記事は2つしか見つかっていない。
後者は gauche という schemeインタープリタを作成されている、川合史郎さんのページだ。
ただ、この2つの記事を読んでも、衛生的マクロの作り方は、よくわからないというのが正直な感想だ。
私の自作インタープリタ作成は、現在この衛生的マクロと格闘中。
年内にはなんとか動くようにしたいと思っているが、全く目処はたっていない。
defineの中にdefineが書ける
こちらのページの例をお借りすると
http://www.nct9.ne.jp/m_hiroi/func/abcscm10.html
(define (my-map func)
(define (map1 ls)
(if (null? ls)
'()
(cons (func (car ls)) (map1 (cdr ls)))))
map1)
こんな事が出来てしまう。
Common Lisp で局所関数を定義するための flet と labels は、なんてインタープリタやコンパイラを作成する人に優しいんだろうと感心してしまった。
そして、私は、defineの中にdefineを書く文を、インタープリタで実装する方法が全く思い浮かばない。
ラベル付きlet
(let (<束縛仕様>*) <末尾本体>)
(let <変数> (<束縛仕様>*) <末尾本体>)
ラベル付きletは、たぶんCommon Lispにはない筈。
letの次の変数は、何に使うかというと、この変数名を関数として呼び出すとループになる。(驚き)
condも意外な違い
(cond <節1> <節2> ...)
<節> は二つの形式のいずれか一つをとる。
(<テスト> <式1> ...)
ここで <テスト> は任意の式である。あるいは
(<テスト> => <式>)
Common Lispの t が elseに変わるのは知っていたが、 =>という構文は初めてみた。(驚き)
他にも色々
書き出すと、キリがないので、このあたりにしておくが、
- 分数
- exact (正確数), inexact
- char-foldcase
などに、苦しめられた。(今も苦しんでいるかも)
インタープリタ作成者のための日本語の記事は本当に少ない
『schemeを学習するための日本語の記事は多数ある。』
色々な大学のサイトにも、schemeを学習するための資料がある。
(ほとんどが2000年頃だが、今でも大学で、schemeを教えているのだろうか。それとももうパイソンに変わっているのだろうか。気になる)
『しかし、インタープリタ作成者のための日本語の記事は本当に少ない』
もしSchemeの仕様書は50ページしかないので、誰でも簡単に作れる
が本当だとしたら、Schemeを作成した日本人が、5人や10人ぐらいはいて、記事を残してくれていても、いい筈だと、私は思う。
『それがないんだからscheme作りは簡単じゃない』と言いたい。
参考になりそうな記事をいくつか
- お気楽 Scheme プログラミング入門
頻繁に参照させていただいている、上記のシリーズの中に
●micro Scheme 編 というシリーズがある。
ここにインタープリタ作成の概要は、書かれている。
ただし、私が知りたかった call/ccの事は、たぶん書かれていない(筈)。
2.魔法言語リリカル☆Lisp
https://lyrical.bugyo.tk/
ゲーム用のスクリプト言語を作ろうとされている様子。
記事はアニメ好きの人にしかわからないかも。(私はアニメ好きだが)
しかし、githubページに、各種プログラミング言語で書かれたLispの実装があった。
この中に、C言語のソースを吐く小さなコンパイラがあった。ちょっと興味を持っている。
今やっているscheme作りが一段落したら、来年にでも、覗いてみようと思う。
川合さんは偉大だった
gauche を作られた、川合さんは本当に偉大だ。
私はJavaが主食なので、C言語やC++は、よく読めないし、川合さんが書いてくださっている衛生的マクロの記事も、読んでもなかなか理解できない。
それでも、記事を残してくれている事に感謝申し上げます。
schemeインタープリタ自作記事教えてください
(できれば日本語で)良い記事をご存知でしたら、お教えください。
10個ぐらいの関数を実装した記事では、参考にならないので、できれば、shceme base を全部実装したぐらいの記事が読んでみたいです。
Javaで書かれたschemeの実装(kawa, CISC)のソースは、読もうとはしましたが、Clojure同様にJVMの知識が必要になり挫折しました。