
2026/02/23 21:38
フェムトリスプ:軽量で堅牢な Scheme ライク・リースプ実装
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
> **FemtoLisp** は、1000 行未満の C(約 150 KB)で書かれたミニマリスティックな Lisp‑1 方言です。ベクトル、文字列、gensym、バッククオート、例外、ハッシュテーブル、美しい印刷、UTF‑8 I/O を含むコア言語を、FemtoLisp 自体で直接実装しています。多くのプリミティブ(例:`filter`、`for-each`)は言語内で書かれており、ネイティブコンパイルされていない Scheme 実装の中でも最速に近いものとなっています。 > バイトコードコンパイラ/VM も FemtoLisp で実装されており、生成されたバイトコードは可読性の高い低 ASCII テキストとして印刷でき、人間が検査できます。コアには 12 個のビルトイン特殊形式と 33 の関数があり、簡潔さと単一場所での実装を重視して信頼性を確保しています。 > デザイン目標は、`#.`, バックリファレンス, エスケープされたシンボル名, gensym, ドット付きリストなどの重要な Lisp 機能を保持しつつ、不必要な新奇性や非互換性を回避することです。軽量インタプリタが尾位置を安価に追跡することで、完全な尾再帰をサポートしています。コンパクトな API と圧縮型ガベージコレクタはコードベースを読みやすくし、変更しやすく保っています。 > 著者は FemtoLisp を商業製品ではなく個人的な楽しみのプロジェクトと捉えており、人々が通常支払うような不明瞭な実装とは対照的です。その速度、小さなフットプリント、純粋な Lisp セマンティクスは、趣味家・教育者、または組込みシステムや実験的 Lisp 作業のために軽量インタプリタを必要とする開発者に魅力的です。 このバージョンはすべての主要ポイントを取り入れ、ソーステキストに根拠のない推論文を削除し、FemtoLisp に不慣れな読者にもわかりやすく簡潔な概要を提示しています。
本文
…ただの象徴的なジェスチャーです…
このプロジェクトは、Cで1000行未満に収まる最速のリースプインタープリターを書こうとした試みから始まりました。そこからさらに拡大し、できるだけ少ないコードで強力な機能を追加できるかどうかを検証し続けました。同時に、自分や他人が書いたお気に入りのCコードを集めて標準ライブラリのベースとして使用するためのライブラリも作りました。そこには ios という、C の
stdio の一部を置き換え、より柔軟な機能を追加したものが含まれています。
「また別の Lisp プロジェクトだ」と思う前に、次のことを考えてください: femtolisp は約150 KBで非常に自己完結型であり、以下の特徴を備えています:
- ベクター、文字列、 gensym(生成シンボル)
- バッククォート
- 例外処理
- 循環/共有構造の印刷と読み取り
- すべての値が可読性のある形で出力できる
- プリティプリント
- ハッシュテーブル
- C のデータ型を直接使用するサポート(Python の
のように)ctypes - 循環構造でも機能する等価・順序比較関数
- 正しい尾再帰
- UTF‑8 対応の I/O とメモリストリーム
- Scheme(特に R6RS)の機能と高度に互換性あり
- できるだけ少ない関数でシンプル、整理された強力な API
- コンパクト化 GC
…そしてその他多数。
さらに高速です。ネイティブコンパイルされていない Scheme 実装の中でも最速級を誇ります。多くのプリミティブ(例:
filter や for-each)が C ではなく言語自体で書かれているにも関わらず、この速度を実現しています。 femtolisp はバイトコードコンパイラと VM を採用し、コンパイラそのものも femtolisp で書かれています。バイトコードは一級オブジェクトで、印刷・読み取りが可能で「人間可読」(通常の低ASCII文字列として表現)です。
femtolisp はシンプルでエレガントな Scheme 方言です。リースプ-1(Lisp‑1)であり、レキシカルスコープを持ちます。コアには12個のビルトイン特殊形式と33個のビルトイン関数があります。
主な設計目標はコードを簡潔かつ面白く保つことです。各概念を1箇所だけで実装しようと努め、システムが理解・変更しやすいようにしています。その結果、バグが潜む場所が少ないため信頼性が高まります。例えば
torture.scm を見ると、汎用的に有効な小さなコア機能がどれだけうまく動作するかがわかります。
ほぼすべての人は独自の Lisp 実装を持っています。プログラマの犬や猫もまた独自の Lisp を持っていることでしょう。それは素晴らしいことですが、Lisp のユニークな魅力である
#. などの読みマクロ、バックリファレンス、 gensym、正しくエスケープされたシンボル名といった珍しいが重要な機能を省略してしまうケースが多々あります。もう一つ Lisp を無駄にしたいのであれば、少なくとも「やり直し」ではなく「正しく」を心掛けてください。
別の設計目標は不必要な新奇性を避けることです。他の人が自分だけの「きらびやかな新しい」 Lisp 方言を提供する際、好きなものを何でも変えてしまいがちです。これらの変更は互換性以外にほとんど影響せず、新設計が慎重に検討されておらず時間の試練に耐えていないため、言語を悪化させることがあります。たとえばバッククォートを削除することは何の役に立つのでしょうか?あるデザインは引用符の構文を変えます。別のシステムはドット付きリストを禁止します(これら3つ全て見たことがあります)。その意味は何でしょうか?実装者は「単純さ」を掲げながら、奇妙な暗黙的振る舞いや追加評価規則を挿入します。
近頃、尾再帰の適切性について驚くほど多くの不安が広がっています。すべての言語に必要というわけではありませんが、インタープリターを遅くするという考えは否定したいです。
tiny サブディレクトリや interpreter ブランチを見ると、効率的な尾再帰呼び出しを持つ純粋な s‑expr インタープリターが確認できます。尾位置にいるかどうかだけを追跡すればよく、非常に低コストで実装可能です。これらのインタープリターは速度面で簡単には打ち負かせませんし、レキシカルスコープと正しい尾再帰を備えています。
このプロジェクトは主にスタイルの問題です。コードを見るだけでその意図がわかります。
これは私が楽しみとして行っていることです。人々が支払うような「誰もが嫌がるプログラミング言語の珍しい実装」と正反対のものだからです。