
2026/05/10 6:46
リスト風の Rust
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
RLisp は、Rust のパフォーマンスと安全性を享受しつつ、LISP の S 式構文の可読性をもたらすための独自のソリューションを提供します。
rustc を介して直接ネイティブバイナリにコンパイルされるため、ランタイム環境やガーベジコレクターの使用は不要となり、所有権、借用、ライフタイム、ジェネリック、トレイト、パターンマッチングなど、Rust のコア機能を完全にサポートしています。インストールは簡単で、GitHub リポジトリをクローン(git clone https://github.com/ThatXliner/rlisp.git)し、cargo install --path . を実行するだけです。このツールには、LISP ファイルを変数化するためのコマンドラインユーティリティ(rlisp compile)、ビルド(rlisp build)、実行(rlisp run)が組み込まれています。開発者は非対応の機能のために生の Rust コードをそのまま使用するために (rust "...") フォームを採用でき、マクロは Runt のプロシージャルマクロに依存せず、(quasiquote)、(unquote)、(unquote-splicing) などの慣れ親しんだ LISP 構造体を利用してコンパイル時の変換を実行できます。&rest でキャプチャされた可変引数は unquote-splicing を使用してマクロ出力に平坦化できます。言語は (while ...)、(loop ...)、(for ...) などを含む標準制御構造と解像度付きイテレータをサポートし、型注釈を受け取る typed クロージャ(例:((x i32) (y i32)) -> i32)および引数を明示的に移動するための move キーワードを提供します。可視性修飾子は Rust の慣習に従います(pub、pub(crate)、pub(super))。このプロジェクトは MIT ライセンスでリリースされており、マクロ開発を簡素化し、バランスの取れた括弧の構造的編集を可能にし、Rust セマンティクスを低い構文障壁で提供することを目的としています。本文
rlisp: RUST 言語のセマンティクスと LISP 構文
rlispとは、Rust のセマンティクス(所有権、借用、ライフタイム、ジェネリック型、トレイト、パターンマッチなど)をそのまま維持しつつ、LISP の構文(S-式)を採用したトランスパイラです。S-式を読み込み、中間表現として Rust コード(
.rs)を生成し、最終的にバイナリへコンパイルします。
特徴:
- ランタイムなし、GC 不要: スタンダードな Rust の動作(コンパイラ
が行う型検査、借用検査、最適化など)のみを利用します。rlisp は構文変換だけの役割を担います。rustc - セマンティックギャップゼロ: Rust が持つあらゆる機能が S-式で自然に表現可能です。
インストール
git clone https://github.com/ThatXliner/rlisp.git cd rlisp cargo install --path .
使い方
rlisp compile file.lisp
ファイルをトランスパイルし、
を生成します。file.rsrlisp build file.lisp
トランスパイルして、
でコンパイルします。rustcrlisp run file.lisp
トランスパイル、コンパイル、実行を一気に行います。
構文マッピング
| LISP | Rust |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
注釈:
- 二項演算子(
,+
,-
,*
,/
,==
,!=
,<
,>
など)はインフィックス表記に変換されます。例えば、&&
は(+) a b
へと展開します。(a + b)
マクロ
rlisp のマクロは、コンパイル時の S-式トランスフォーマーです。
proc_macro クレート、トークンストリーミング、syn/quote などの複雑な仕組みは使用せず、マクロを「S-式から S-式へ変換する関数」としてのみ考えます。
マクロ本体では、LISP から由来する以下の 3 つの特殊形式を利用します:
| 形式 | 意味 |
|---|---|
| 「このテンプレートを引用しつつも、内部にあるアンクォートを許可する」——タグ付きテンプレートリテラルのような挙動です。 |
| 「ここで name の値を挿入する」——テンプレート上の穴(ホール)です。 |
| 「リスト name を surrounding list にスパイスする(埋め込む)」——複数の形式を挿入するために使用します。 |
quasiquote は、「アンクォートを除いたこの正確な S-式を返す」と捉えれば良いでしょう。これをなくすと、各括弧を list や cons で手動で構築しなければなりません。
;; 条件が満たされた場合、本体を実行する when マクロの定義 (defmacro when (condition &rest body) (quasiquote (if (unquote condition) (do (unquote-splicing body))))) ;; マクロ展開例: ;; (when (> x 10) (print "big") (print "huge")) ;; → (if (> x 10) (do (print "big") (print "huge"))) ;; → if x > 10 { print("big"); print("huge") } (defmacro double (x) (quasiquote (+ (unquote x) (unquote x)))) ;; (double 21) → (+ 21 21) → 21 + 21 (fn main () () (let x 21) (println! "Double: {}" (double x)) (when (> x 10) (println! "x is greater than 10") (println! "this too")))
&rest は残りのすべての引数をリストにキャプチャし、unquote-splicing はそのリストを surrounding 形式へフラット化(展開)します。これにより可変引数のマクロが動作します。
ループ処理
(while (> x 0) (println! "{}" x) (-= x 1)) (loop (println! "tick")) (for x in 0..10 (println! "{}" x)) ;; デストラクチャリング付きの for ループ (for (i val) in (. v iter) enumerate (println! "{}: {}" i val))
クロージャ
;; タイプなし (let add (lambda (x y) (+ x y))) ;; リターン型を付与したtypedクロージャ (let mul (lambda ((x i32) (y i32)) i32 (* x y))) ;; 所有権を持つクロージャの生成 (let s "hello") (let greet (lambda move () (println! "{}" s)))
モジュール、可視性、インポート
(pub fn public_api () i32 42) (pub (crate) fn internal () i32 0) ;; pub(crate) (pub (super) fn parent_visible () i32 1) ;; pub(super) (pub struct Config (pub host String) ;; パブリックなフィールド (port u16)) ;; プライベートなフィールド (pub mod utils ;; インラインモジュール (pub fn helper () i32 1) (fn private () i32 0)) (mod external_lib) ;; 外部モジュールの宣言 (use std::collections::HashMap) (use std::io::{self,Write,Read}) (use std::fmt::Display as Fmt)
インライン Rust
rlisp がネイティブで表現できないことは、
(rust "...") を使って生の Rust コードにドロップインできます。文字列は LISP のエスケープシーケンスを反転させた状態で生成された .rs ファイルへそのまま出力されます(verbatim)。
(fn raw_example () i32 (rust "let x: i32 = 42; x * 2")) (fn main () () (rust "let message: &str = \"from raw Rust\";") (println! "{}" (rust "message")))
なぜ作るのか?(Why)
主に趣味として、構文を取り払いながらセマンティクスだけを維持した「Rust の姿」を探索するためですが、実用的な側面もあります:
- マクロが簡素化される。 LISP では、マクロはコンパイル時に S-式を受け取り S-式を返す単純な関数であり、トークンストリーミングや
の儀礼なしで動作します。これは LISP が Rust に持ち寄った「キラー特徴」です。proc_macro - 構造化編集。 S-式はスリップ(全体読み込み)、バフ(全体書き出し)、転置(行列転換)、ラップ(ネスト)といったエディタツールによる操作に対して非常に扱いやすく、すべての操作が構築によってバランスが取れています。
- 均質な構文。 表現式、ステートメント、型、パターンに区別がありません。すべて S-式です。
の腕や関数のシグネチャには、すでに知っている構文が使われています。match
ライセンス
MIT