世界を動かす技術を、日本語で。

Lispへの道: なぜLispなのか

2026年7月9日原文(scotto.me)

概要

  • Lispの初見時に感じる違和感、その理由
  • Lisp特有の強力な拡張性とマクロ機能の説明
  • コードとデータが同じ構造を持つ「ホモイコニシティ」
  • REPL駆動開発によるライブシステムの特徴
  • Lispがプログラマに新しい思考法を与える理由

初めてのLisp:戸惑いと新しい視点

  • 多くのプログラマがLispコードを見ると「 何これ?」と感じる驚き
  • 括弧だらけ の構文、独特なインデント、formatの第1引数の使い方など、他言語と異なる記法
  • 最初はコードの読み方に慣れる必要があるが、 パッケージやシンボルの扱い、プロジェクト作成、ライブラリの導入、REPLや条件分岐・リスタートの使い方も学ぶ必要
  • アルゴリズム構築の 思考様式の転換 が最大の壁
  • Lispは多くの一般的な言語よりも 学習曲線が急 だが、他言語では得られないスキルや視点を獲得可能

Lispの強み:他言語にはない表現力

  • Lispでは 他言語で不可能なこと が可能
  • アルゴリズムや構文を 自由に拡張・変形 できる柔軟性
  • Paul Grahamによる Blubパラドックス :強力な言語を知らないと、その力を認識できない現象
  • Louis Armstrongの「 ジャズを問うなら理解できない」という言葉と同じく、Lispの本質は使ってみないと分からない
  • Lispを学ぶことで、 プログラミング言語の本質的な力 を体感し、思考方法が変化

Lispの拡張性:マクロによる言語の進化

  • Lispは 自己拡張可能 な「プログラム可能なプログラミング言語」
  • 単なるプログラムを書く以上に、 言語そのものを拡張 できる
  • マクロ(macro)による新しい構文や制御構造の追加
  • 他言語(C, Rust, Swiftなど)のマクロは主にボイラープレート削減だが、 Lispのマクロは言語自体の拡張 が可能
    • 例:Cのwhile構文をLispでマクロとして実装可能
  • マクロは引数を 評価せずに受け取り、構文変換 を行うため、関数とは本質的に異なる
  • macroexpandコマンドで マクロ展開の結果 を確認可能

コードはデータ:ホモイコニシティ

  • Lispは リスト(list) を基本構造とし、プログラムもデータもリストで表現
  • シンボリック表現(s式): アトム(数字・文字列・シンボル) または リスト から成る
  • コードとデータの区別は '(クォート) によって制御
    • ( + 1 2 ) はコードとして評価され、'(+ 1 2) はデータとして扱われる
  • コードそのものをデータとして 自在に操作・変換 できるため、プログラムがプログラムを生成可能
  • この性質を ホモイコニシティ と呼び、Lispマクロの本質的な基盤

マクロによる抽象化と効率化

  • マクロで 新しい構文や制御構造 を作成し、コードの簡潔化
  • 繰り返し構造やリソース管理 など、用途特化の構文を自作可能
  • 複雑・エラーが起きやすい処理も 抽象化して安全に隠蔽
  • パフォーマンス向上コード生成 も可能

ライブシステムとしてのLisp:REPL駆動開発

  • Lispは ライブシステム として機能し、他言語とは異なる開発体験を提供
  • 開発の第一歩は Lispプロセスを起動し、REPLに接続 すること
  • REPL(Read-Eval-Print Loop)で 即時評価・即時反映 が可能
  • 他言語では「書く→コンパイル→実行→デバッグ」の繰り返しが必要だが、Lispでは プロセスを止めずに即座に反映
  • 関数・マクロ・変数の定義や再定義 が即時に有効化(バインディング)
  • この開発スタイルは REPL駆動開発 と呼ばれ、Lisp発祥の「ホットリロード」機能の源泉
  • JavaScriptのホットリロードもLispの影響を受けているが、Lispでは 追加ツール不要で標準機能
  • プロセスは数週間継続稼働し、 ライブでのデバッグ・テスト・修正 が可能

Lispがもたらす新しいプログラミング体験

  • Lispを学ぶことで、 プログラミング言語の可能性 を体感
  • 言語を自分の問題領域に合わせて成長 させ、その上でプログラムを書くという発想
  • 他言語では得られない 抽象化・拡張・柔軟性 を獲得
  • Lispを使いこなすことで、 より良いプログラマ へと成長可能

Hackerたちの意見

このウェブサイト、構文ハイライトにバグがあるみたい。投稿テキストに含まれてるコードが黒くなってて、マウスで選択すれば実際のテキストは見えるけど。Chromeのデスクトップ版とiPadのSafariでも同じバグが出てる。

メトゥー

最初に思ったのは、この記事が編集されてるのかなって、笑

これ、FirefoxとChromeの両方で出てるよ。

背景色を変えるときは、必ず前景色も設定しないとダメっていう典型的な例だね。そうしないと、黒いブロックの上に黒い文字が乗っちゃう。ブラウザがダークモードなら問題ないかもしれないけど。対策としては、ブラウザのデバッガーでコード要素の一つを開いて、:not(pre) > codeスタイルにcolor: whiteを追加するのがいいよ。

MacOSのChrome? コードブロックはLinuxの{firefox, chromium, brave}でも問題ないよ。みんなQtを使ってると思う。

報告ありがとう。君のコメントを読んですぐにエラーを修正したよ。

Lispには本当に強力でユニークな部分があるけど、こういう記事にはREPLやホットリロードを含めるのはやめてほしいな。前者は解釈型言語(と一部のコンパイル型言語)ではずっと当たり前のことだし、後者は特にユニークでも広く使われてるわけでもないからね(ホットリロードは状態やパッチ処理と絡むから、論理的に考えやすくするために世界をリセットするのがベストプラクティスとされてる理由がある)。

大体同意。ホットリロードの進んだ部分がすでにCommon Lispでカバーされてることを強調する価値はあると思う。REPLも直接入力するために使われることは少なくて、実行中のイメージとツールがやり取りするための非常に強力なインターフェースだってことも同様。ただ、今の時代にこれらが存在するだけでは特に注目されることはないよね。

前者は解釈型言語ではずっと当たり前のことだ 俺も昔、Clojureに入ってた頃はそう思ってた。でも、Lispの人たちがREPLについて話すときは、単にコマンドを簡単に評価できるインタラクティブなCLIのことじゃなくて、自分のプログラムをライブセッションに接続して、テキストエディタ内で素早くフォームを評価できる能力について話してることが多いって気づいたのはずっと後だった。これによって、他の解釈型言語よりもずっとインタラクティブな開発ができるんだよね。

Clojureはデフォルトで不変だから、ホットリロードが本当に実現できるんだよね。JVMだけじゃなくて、リスプの中でもそうみたい。

すべてのLisp方言がしっかりしたホットパッチシステムを持ってるわけじゃないんだ。OOPシステムは慎重に設計しないといけないよね。クラス定義がリロードで上書きされるとき、既存のインスタンスはどうなるの?Common Lispの方言はこういう質問に対して役立つ答えを持ってるけど、出会うすべてのLispがそうとは限らないよ。Bashだってホットリロードをサポートしてるし、私はモジュールを開発して、その場で更新できるようにしてる:$ . /path/to/script.sh

Hacker Newsで議論の続きを見る