プログラミング
Racketへの親しみやすい入門
A Friendly Introduction to Racket (geometridae.bearblog.dev)
要約
Racketは、Lispから派生した強力なプログラミング言語であり、コードをデータとして扱う「ホモイコニシティ」という特徴を持ちます。この記事では、Lispの歴史的背景からRacketの基本的な構文、関数型プログラミング、再帰、そして独自の言語を構築できる能力までを解説し、プログラミングの新たな視点を提供します。
全文翻訳
Racketへの親しみやすい入門
11 Aug, 2026
「Lispは、最終的に理解できたときの深い啓発体験のために学ぶ価値がある。」 — Eric S. Raymond
ようこそ。今日は、プログラミング界で最も古く、最もユニークなファミリーの一つに属する言語を学びます。コードがデータであり、括弧が純粋な構造であり、プログラムがプログラムを書くことができる言語です。このチュートリアルの終わりまでには、あなた自身の構文を書き上げることになります。
少し歴史を
Lispは1958年にMITのJohn McCarthyによって発明されました。文脈として、これは現在も使用されている2番目に古い高水準言語です(1957年のFortranのみが1年早くこれを上回ります)。Pythonは1991年に、JavaScriptは1995年に登場しました。Lispはそれらよりも30年以上早く、現在「モダン」と見なされている多くのアイデアがそこで生まれました。
ガベージコレクション — Lispのために発明されました。
ファーストクラス関数 — 関数を引数として渡すこと、現在はどこでも標準です。
REPL — Python、Node、Juliaが今日持っているインタラクティブな読み込み-評価-表示ループはLispで始まりました。
条件式としての式 — 値を返すifです。
ホモイコニシティ — コードは言語自体のデータ構造です。これは大きなポイントです。最後にこれに戻ってきます。
数十年間、Lispは人工知能の言語でした。70年代と80年代には、Lispを直接実行するために設計された物理的なコンピュータがありました:SymbolicsとLMIによって構築されたLispマシンです。その後、「AIの冬」が到来し、資金が枯渇し、Lispはスターからカルト言語へと転落しました。しかし、興味深いアイデアは死なず、変異します。それがリスプの美しさの一部です。
LispからSchemeへ、そしてRacketへ
1975年、Gerald SussmanとGuy SteeleはSchemeを作成しました:ミニマリストでエレガント、ほとんど数学的なLispです。Schemeは、プログラミング教育のための学術界のお気に入りの言語となりました(伝説的な書籍SICP Structure and Interpretation of Computer ProgramsはSchemeで書かれています)。1995年、Matthias Felleisenのグループは、教育とプログラミング言語研究のために設計されたSchemeであるPLT Schemeを作成しました。2010年にRacketと改名され、今日ではScheme以上のものになっています:言語を構築するための言語です。その非公式なモットーは「言語指向プログラミング」です:もしあなたの問題が独自の言語を必要とするなら、Racketを使えば午後でそれを構築できます。
年 イベント
1958 McCarthyがMITでLispを発明
1975 SussmanとSteeleがSchemeを作成
1984 Common Lispが標準化
1995 PLT Scheme(現Racket)誕生
2007 Clojure誕生(JVM上のLisp)
2010 PLT SchemeがRacketに改名
今日 あなた、これを読んでいるあなた、括弧を書こうとしているあなた UwU
今日、誰がLispを使っているのか?
あなたが思うよりも多くの人々が使っています:Clojureは銀行、航空会社、スタートアップ(ラテンアメリカ最大のデジタルバンクであるNubankはClojureで稼働しています)で本番稼働しています。Common Lisp(SBCLコンパイラ付き)は、エキスパートシステム、航空機の飛行計画(Google Flightsを支えたITA SoftwareはGoogleに買収されました)、科学計算で今も生きています。Emacs Lisp — 何百万人もの人々が、エディタがLispインタプリタであるため、知らず知らずのうちに毎日Lispを実行しています。Guile/Guix — 全てのLinuxディストリビューションがSchemeで100%設定されています。Racketは独自の年次カンファレンス(RacketCon)、活発な学術的および芸術的なコミュニティを持ち、言語研究、形式検証(Rosette)、タイポグラフィと出版(Pollen)、そして世界中の教育で使用されています。そして新しいLispが次々と登場しています:Fennel(LuaにコンパイルされるLispで、ゲームで人気)、Janet、Hy(Python上のLisp)...。
TADCファンのためのイースターエッグ:The Amazing Digital Circus(エピソード8、「hjsakldfhl」)で、KingerがCaineをリセットしようとターミナルを開いたとき、Caine(1996年に構築されたクリエイティブAI)がLispでプログラムされているのが見えます。ファイル名は文字通りCaine-core.lispです。
インストール(5分)
https://racket-lang.org にアクセスしてください。
お使いのシステム(Linux、macOS、Windows)用のインストーラーをダウンロードしてください。
付属の環境であるDrRacketを開いてください。DrRacketには2つの領域があります:上部には定義(プログラム)を書き、下部にはライブ実験用のREPLがあります。
定義領域の最初の行に、以下のように書きます。
#lang racket
この行は、Racketがどの言語を使用しているかを伝えます(覚えておいてください:Racketは言語工場なので、1つを選択する必要があります)。
ターミナルを好む場合:racketコマンドはREPLを提供し、racoはパッケージマネージャーとツールコマンドです。
最初の接触:すべては式である
REPLで、以下を試してください。
> (+ 1 2)
3
> (* 3 (+ 2 2))
12
> (string-append "hello " "world")
"hello world"
Lispのルールは1行で収まります:すべては (演算子 引数1 引数2 ...)。常に。例外はありません。覚えるべき演算子の優先順位はなく、何かのための特別な構文もありません。
(+ 1 2) は加算します。
(if ...) は決定します。
(define ...) は名前を付けます。
最初は威圧的に見える括弧は、実際には恣意的なルールの完全な欠如です。1週間後、それらを見なくなります。
定義と関数
#lang racket
(define pi-approx 3.14159)
(define (circle-area r)
(* pi-approx r r))
(circle-area 2) ; => 12.56636
名前付きのdefineは定数を作成します。(name arguments...) という形式のdefineは関数を作成します。コメントは ; で始まります。無名関数はlambdaを使用します(そう、1930年代のチャーチのラムダ計算は、これらすべて理論上の祖父です):
(lambda (x) (* x x)) ; 名前を持たない関数
((lambda (x) (* x x)) 5) ; => 25、直接適用
リスト:Lispの中心
LispはLISt Processingの略です。リストは基本的な構造です。
(list 1 2 3) ; => '(1 2 3)
'(1 2 3) ; 同じもの、「引用」されたもの
(first '(1 2 3)) ; => 1
(rest '(1 2 3)) ; => '(2 3)
(cons 0 '(1 2 3)) ; => '(0 1 2 3)
(length '(a b c)) ; => 3
引用符 ' に注意してください。これはRacketに伝えます:これを評価しないでください、それはデータです。その詳細を覚えておいてください。それが最後のトリックへの扉です。
高階関数
ここでRacketが輝きます。関数を他の関数に渡すことは、世界で最も自然なことです。
(map (lambda (x) (* x x)) '(1 2 3 4 5)) ; => '(1 4 9 16 25)
(filter even? '(1 2 3 4 5 6)) ; => '(2 4 6)
(foldl + 0 '(1 2 3 4 5)) ; => 15
mapは変換し、filterは選択し、foldlは蓄積します。それら3つの関数があれば、forループを一切書かずにほとんどのリスト問題を解決できます。
再帰:螺旋状に考える
Lispでは、「N回繰り返す」とは考えず、「ベースケースは何で、それにどう近づくか?」と考えます。
(define (factorial n)
(if (= n 0)
1
(* n (factorial (- n 1)))))
(factorial 5) ; => 120
そして視覚化するために、何かを描きましょう。Racketにはグラフィックライブラリが付属しています。
#lang racket
(require 2htdp/image)
(define (sierpinski level)
(if (= level 0)
(triangle 8 "solid" "purple")
(let ([t (sierpinski (- level 1))])
(above t (beside t t)))))
(sierpinski 6)
これをDrRacketに貼り付け、「実行」を押すと、画面にシェルピンスキーの三角形が表示されます。
グランドフィナーレ:コードを書くコード
引用符 ' を覚えていますか?それはコードをデータに変えます。見てみましょう。
'(+ 1 2) ; => リスト (+ 1 2)、数値の3ではありません
(first '(+ 1 2)) ; => シンボル +
(eval '(+ 1 2)) ; => 3。あなたはデータをコードとして評価しました。
あなたのプログラムはリストです。リストを構築できます。したがって、プログラムでプログラムを構築できます。これがホモイコニシティであり、LispにはCのようなテキストマクロではなく、真のマクロがある理由です。コードを受け取り、何も実行される前にコードを返す関数です。
Racketにはwhileループがありませんか?発明してみましょう。
(define-syntax-rule (while condition body ...)
(let loop ()
(when condition body ... (loop))))
(define counter 0)
(while (< counter 5)
(displayln counter)
(set! counter (+ counter 1)))
あなたは言語を拡張しました!Lispでは、構文はあなたのものです。Alan KayはLispを「ソフトウェアのマクスウェルの法則」と呼びました:すべてがそこから導き出せる小さなコアです。
次は何?
How to Design Programs — Racketが設計された中心となる書籍、オンラインで無料です。
The Racket Guide — 公式ドキュメント、最高のものの一つです。
Beautiful Racket — 独自の言語の構築を学びます。
SICP — 完全な啓発を望むなら、古典中の古典です。