Lune — the Lazy and Native programming language
コンパイラが教えてくれる、遅延評価の関数型入門言語。 エラーも、その解説も、母語で読めます。
Lune is a teaching-first functional language: lazy by default, with diagnostics that speak your native language. If you prefer English, start with documents/TUTORIAL_EN.md — every diagnostic and explanation defaults to English.
▶ Playground(インストール不要) · 診断カタログ · チュートリアル
プロローグ — 全員、部活に入ること
転校初日に知らされた校則がこれだった。「全生徒、いずれかの部に所属すること」。
運動部は続く気がしない。文化系の一覧を眺めていたら「プログラミング部」とある。パソコンで何か打っていれば終わる、いちばん楽そうなやつだ。僕は入部届を出した。
部室のドアには、こう書かれていた。
部訓: 必要になるまで、やらない。一度やったことは、忘れない。
……楽そうな部、で合ってるよな?
入部初日 — さっそく間違える
プログラミング部にはいってみたら、部員は先輩3人だけ、男子は自分だけだった。はたしてやっていけるのかな?
「じゃあ転校生くん、まず書いてみて」と真知(まち)部長。見よう見まねで打ったら、初日からエラーを出した。
let count = 10
let total = cont + 5
$ ./bin/lune --check --lang ja guide.lune
error[TYP0001]: 未定義の名前: cont
--> guide.lune:2:13
|
2 | let total = cont + 5
| ^^^^ この名前は定義されていない
= hint: もしかして `count` ですか?
= help: 詳しくは `lune explain TYP0001 --lang ja` を実行してください
身構えた僕に、部長は画面を指しながら言った。「読み方を教える。上から順に」
TYP0001— エラーの出席番号(診断コード)。あとで調べるときの索引になる^^^^— 問題の場所そのもの。まずここを見る= hint:— 次の一手。正解の候補まで書いてある= help:— もっと深く知りたいときの案内
「うちの部では、エラーは赤点じゃなくて教材。読めるようになったら、もう半分書けるのと同じ」
思っていたのと違う。この部、楽じゃない。でも、理不尽でもなかった。
部員紹介 — 教えてくれる先輩たち
- 真知(まち)部長 —
matchの抜けを絶対に見逃さない。「Blueのケースがありません」と反例つきで指摘してくる(TYP0007)。書きすぎれば「そのケースには到達しません」(TYP0009)。null もT?の型として扱わせ、?./??/ フロー narrowing まで仕込んでくる。厳しいが、指摘には全部理由がある。 - 英美(えいみ)先輩 — 解説担当。全30の診断コードに「意味・発生する最小例・直し方」の詳解を用意している(
lune explain CODE、REPL では:explain)。日本語でも英語でも説明できる(--lang ja)。全文は診断カタログに貼り出されている。 - 直美(なおみ)先輩 — 赤ペンと清書の担当。typo は did-you-mean の候補で機械的に直してくれるし(
lune fix)、提出前には正準スタイルに整えてくれる(lune fmt)。整形で意味が変わっていないことを再パースで検証してから返す、と聞いてこの部の本気度を理解した。
教わる流れは決まっている: 間違える → 読む → explain → fix → 確認。チュートリアル第17章には「指定した診断をわざと出せたら正解」という逆転演習まであって、僕は初日にエラーの出し方から教わった。
部訓の意味 — 「必要になるまで、やらない」(遅延評価)
Lune の値は、必要になるまで計算されない。
let danger = crash()
let answer = 42
answer を評価しても danger は使われないから、crash() は実行されない。「サボりじゃないの。必要なものを、必要なときに、一度だけ。そして一度やったことは忘れない(メモ化)」と部長は言う。
信じられないなら目で見ればいい、と教わったのが REPL の :trace だ。
lune> :trace on
trace on
lune> let y = x + 1
ok # 宣言では何も評価されない
lune> y * 10
force y * 10
force x + 1 # y が必要になって初めて評価される
memo 1 + 1 => 2 # x はメモ化済み。再計算されない
=> 3
=> 30
30 : Int
この校風なら、無限リストとも普通に付き合える。どこまで計算が進んだかは :thunks が見せてくれる。
lune> let nat = naturalsFrom(1)
ok
lune> head(nat)
Some(1) : Option[Int]
lune> :thunks nat
nat : evaluated = Cons(1, <thunk>) # 先頭だけ計算済み。続きは手つかず
放課後 — 部室はブラウザの中にもある
https://koide55.github.io/lune-lang/playground/
家に帰ってからも練習できるように、部室はブラウザの中にもある。処理系(Pure Python)が Pyodide 上でそのまま動くので、インストールは不要。実行・型チェック・整形・自動修正・explain・遅延評価のトレース・日本語/英語の切り替え、全部できる。
REPL もそのまま入っている。 出力ペインを「REPL」タブに切り替えると、lune --repl と同じセッションがブラウザの中で立ち上がる — 束縛は残り、:type も :thunks も :trace も効き、複数行の def も書ける。エディタで書いたプログラムを読み込んで、REPL から突くこともできる。
「新規」で白紙から始められるし、手元の .lune ファイルは「開く」(Ctrl/Cmd+O、エディタへのドラッグ&ドロップでも可)で読み込める。書いたコードは「保存」(Ctrl/Cmd+S)で持ち帰れて、そのまま ./bin/lune に食わせられる。
import で分けたプログラムもそのまま動く。 エディタの上のファイルタブで main.lune の隣にモジュールを足せる(math でも util.text でも)。手元でファイルを並べたときとまったく同じ解決規則で、実行も型チェックもプログラム全体が対象になる。
資料棚 — ドキュメント
- 教科書『プログラミング言語 Lune』 — 序章+全13章+付録A〜E。腰を据えて体系的に学ぶならこちら。演習には解答付き。1冊にまとめた PDF(A4・167ページ、しおり付き)もあります(原稿は books/)
- チュートリアル(日本語) / Tutorial (English) — 全20章。手を動かして1〜2時間で1周する入門。遅延評価は第2〜6章でじっくり、エラー駆動学習は第17章
- 診断コード索引(日本語) / Error Index (English) — 自動生成、テストで同期を強制
- 言語仕様ほか、documents/ に仕様書一式
- 普及戦略 — この部がどこへ向かうか
入部届 — はじめかた
必要なのは Python 3.10+ だけ。依存パッケージはありません。
git clone https://github.com/koide55/lune-lang.git
cd lune-lang
./bin/lune # REPL(:help でコマンド一覧)
./bin/lune --check --lang ja file.lune # 型チェック(日本語診断)
./bin/lune --eval answer file.lune # ファイルの束縛を評価
./bin/lune --eval answer --trace file.lune # 遅延評価をトレース
./bin/lune explain TYP0007 --lang ja # 診断コードの詳解
./bin/lune fmt --write file.lune # 整形
./bin/lune fix --write file.lune # typo の自動修正
./bin/lune --version # 版番号(バグ報告に添えてください)
書き味の見本は samples/ にあります(ADT・match・レコード・パイプライン |>・nullable・無限ストリームなど)。
pip で入れる
pip で入れると lune コマンドがどこからでも使えます(./bin/lune と同じもの)。
pip install git+https://github.com/koide55/lune-lang.git
lune --check file.lune
LUNE_LANG=ja lune --check file.lune # 既定を日本語診断にする
クローン済みなら pip install -e . で編集可能インストールにもできます。配布名は
lune-lang(PyPI の lune は別のパッケージが使用中)で、PyPI への公開はまだです
(手順は documents/RELEASING.md に用意してあります)。
顧問の先生より — 開発者向け
処理系は lune/ 以下の Pure Python(外部依存なし)。lexer → layout → parser → typechecker → evaluator の各層と、diagnostics / explanations / messages(英日メッセージカタログ)/ formatter / fixer / REPL で構成されています。
PYTHONPATH=. python3 -m unittest discover -s tests # 処理系のテスト
bash books/tools/check_examples.sh # 教科書のコード例を実 CLI で検証
テストは「発行されうる全診断コードに詳解があること」「詳解とメッセージに日本語訳があること」「生成物(診断カタログ)が陳腐化していないこと」まで強制します。間違いを教材にする部なので、自分自身にもそこそこ厳しめです。
CI(.github/workflows/ci.yml)は push と PR のたびに、Python 3.10〜3.14 でこの2つを回し、さらに wheel を組んで lune コマンドが単体で動くところまで確かめます。教科書も同じ CI で HTML と PDF に組み上げます(公開しているものと同じ手順です)。
ライセンス
MIT License。Copyright (c) 2026 Hiroshi Koide。
気づけば、放課後の部室にいちばん長く残っているのは僕になっていた。
Lazy は評価戦略のこと。Native はネイティブコードのこと……ではなく native language(母語) のことだと、英美先輩は最初に教えてくれた。それでは、よい部活動を。
Metadata
Release files for lune-lang 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lune_lang-0.1.0.tar.gz | 233.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lune_lang-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 316.1 kB
Release files / lune_lang-0.1.0.tar.gz
| Download URL | lune_lang-0.1.0.tar.gz |
|---|---|
| Size | 233.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
530dfc4f4b00530f7edad7b609d7294870bf363b58a09d252bde740cb6a594f5
|
|
BLAKE2b-256 checksum How to use checksums |
bb6f70fb566cac2d33eb0ee65f64e1da9def984bc6faeaeab8236793701ed852
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency logRelease files / lune_lang-0.1.0-py3-none-any.whl
| Download URL | lune_lang-0.1.0-py3-none-any.whl |
|---|---|
| Size | 82.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9510fc0100ad75eab7055be05e0592fb43190c1d57cb49d79639ed142b9588e6
|
|
BLAKE2b-256 checksum How to use checksums |
88f2ea4ebf689da43b2eafad4918e79dbdb4368b0afb2b0ffc6de7864c8148eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency log