WHAT'S NEW
CONTENTS
お気楽 Clojure プログラミング超入門
CONTENTS
- 2025/05/14 Clojure の基礎知識 [1]
Lisp はリストが主人公、リストの構造、関数の実行、シンボルと文字列、式の計算、複雑な式を計算する、関数とプログラミング、関数定義、変数とは?、まとめ、問題
- 2025/05/14 Clojure の基礎知識 [2]
変数の定義、局所変数と大域変数、評価しちゃだめ、基本的なリスト操作、リストの分解と合成、リスト操作は非破壊的、可変個引数、マルチアリティ関数、まとめ、問題
- 2025/05/14 条件分岐と再帰定義
条件分岐、述語、複数の術語を組み合わせる、when と when-not、数と算術演算、整数、有理数、実数、算術演算、再帰定義、再帰定義とリスト操作、まとめ、問題
- 2025/05/14 繰り返しと末尾再帰
let による局所変数の定義、累乗の計算、累乗の高速化、複雑な条件分岐、FizzBuzz 問題、繰り返し (dotimes, doseq)、末尾再帰、リストの反転、フィボナッチ関数、loop / recur、まとめ、問題
- 2025/05/14 高階関数と無名関数
高階関数とは?、マップ関数、マップ関数の作成、フィルター、畳み込み、apply、無名関数、等値の判定、リストの探索、連想リスト、内包表記、まとめ、問題
- 2025/05/14 クロージャ
局所変数の有効範囲 (レキシカルスコープ)、ダイナミックスコープ、無名関数と局所変数、高階関数と無名関数、関数の中で関数を定義する、無名関数とクロージャ、関数を生成する関数、カリー化、まとめ、問題
- 2025/05/14 ベクタ
配列、ベクタの基本的な操作、要素の追加と削除、要素の更新、ベクタの操作関数、線形探索と畳み込み、二分探索、ソート、分配束縛、doseq と for、組み合わせの数、プログラムの高速化、まとめ
- 2025/05/22 マップとセット
マップとは?、マップの生成、マップの基本的な操作、データの追加と削除、データの更新、マップの操作関数、マップの分配束縛、セットとは?、セットの生成、セットの基本的な操作、データの追加と削除、集合演算、コレクションの操作関数、簡単な例題、まとめ
- 2025/05/25 順列と組み合わせ
順列の生成、バックトラック法の実装、プログラムの作成、高階関数版の作成、順列をリストに格納する、要素の選択、順列の生成 (2)、組み合わせの生成、組み合わせをリストに格納する、問題、補足: 要素に重複がある場合
- 2025/05/27 生成検定法
小町算、大町算、覆面算、Eigth Queens Problem、変数値の更新、マスターマインド
- 2025/05/29 経路の探索
グラフとは?、隣接行列と隣接リスト、マップによる方法、バックトラックによる探索、幅優先探索、経路の管理、プログラムの作成、反復深化、反復深化による経路の探索、水差し問題、容器の操作、深さ優先探索による解法、幅優先探索による解法、反復深化による解法
- 2025/05/31 マクロ
マクロの定義、マクロと関数の違い、マクロとコンパイラの関係、スタックの操作、マクロの問題点、シンタックスクォート
- 2025/05/31 メモ化と遅延評価
たらいまわし関数、メモ化による高速化、メモ化関数、遅延評価による高速化、クロージャによる遅延評価
- 2025/06/05 遅延シーケンス (1)
遅延ストリームの構造、遅延シーケンスの基本操作、遅延シーケンスの生成、遅延シーケンスの操作関数、高階関数、map の便利な使い方、flatmap、take-while と drop-while、組 (pair) を生成する遅延シーケンス
- 2025/06/06 遅延シーケンス (2)
格子点の生成、遅延シーケンスの併合、集合演算、ハミングの問題、順列の生成、8クイーンの解法、エラトステネスの篩、より高速な方法、双子素数、プログラムリスト
- 2025/06/09 継続渡しスタイル
継続とは?、継続渡しスタイルとは?、再帰呼び出しと継続渡しスタイル、二重再帰と継続渡しスタイル、再帰呼び出しの中断、CPS による木の巡回、CPS による継続の保存と実行の再開、木の巡回と遅延シーケンス、ツリーマッチング、末尾再帰をスタックオーバーフローせずに実行する、CPS での実行
- 2025/06/11 整数の論理演算とビット操作
基本的な論理演算、基本的なビット操作、組み合わせの生成、組み合わせに番号を付ける、ちょっと便利なビット操作、ビットが 1 の個数を求める、パズル「ライツアウト」、ライツアウトの解法、高速化、解法プログラム、実行結果
- 2025/06/14 幅優先探索とスライドパズル
8パズルの説明、プログラムの作成、幅優先探索による解法、実行結果、双方向探索、プログラムの作成と実行結果、最長手数の求め方、プログラムの作成 (3)、実行結果 (3)、問題
- 2025/06/16 反復深化と下限値枝刈り法
ペグ・ソリティア、Hoppers、跳び先表とペグの移動、反復深化による Hoppers の解法、実行結果、反復深化による8パズルの解法、実行結果、下限値枝刈り法、プログラムの作成、実行結果、問題
- 2025/06/24 レコード
レコードの基本、カプセル化、キュー、キューの実装、プロトコル、ポリモーフィズム、deftype、スタック、プロトコルの定義、immutable なスタック、mutable なスタック
- 2025/06/27 二分探索木
木構造、二分木、二分木の実装、データの探索、データの挿入、データの削除、二分木の巡回、実行例、プログラムリスト1、プログラムリスト2、問題
- 2025/07/02 二分探索木 (mutable 版)
mutable な Node、データの挿入、データの削除、Tree の作成、簡単なテスト
- 2025/07/07 名前空間
名前空間とは?、refer、require、-main 関数とコマンドライン引数、簡単な例題
- 2025/07/13 ファイル入出力
標準入出力とは?、read と print、spit と slurp、ファイルのアクセス、cl-format、バイナリファイルの操作、byte 型配列、ファイルのコピー、問題
- 2025/07/16 例外処理
例外の捕捉、try の使い方、例外の送出、ex-info と ex-data、大域脱出、finally 節、逆ポーランド記法、逆ポーランド記法の計算、演算子の定義、数式の計算処理、数式の入力処理、簡単な実行例
- 2025/07/18 パズル Fours Four
問題の説明、プログラムの作成、数式の生成、数式の計算、解法プログラムの作成、実行結果
- 2025/07/24 マルチメソッド
defmulti、defmethod、データ型以外の値でメソッドを選択する、ディスパッチ値の階層構造、メソッドの選択、メソッドの競合
- 2025/07/26 複素数
Clojure の実数、データ型の定義、基本的な関数、四則演算、実行例、プログラムリスト
はじめに
Clojure (クロージャー) は Rich Hickey 氏によって設計・開発された関数型プログラミング言語で、2007 年に公開されました。Clojure は Lisp 方言の一つで、プログラムを S 式 で記述します。( ) だけではなく、[ ] や { } も使うところが Lisp とは異なります。また、Java プラットフォーム (Java 仮想マシン) 上で動作するので、Java と簡単に連携することができます。イミュータブル (immutable) なデータ構造をサポートしていて、並行処理に強いプログラミング言語です。
M.Hiroi は Clojure でプログラミングするのは初めてです。最初は M.Hiroi が知っている Lisp / Scheme の機能を中心に、簡単なプログラムを作りながら Clojure を勉強していきたいと思っております。なにぶん初心者が作るプログラムなので、間違いや Clojure の作法に反することがあるかと思います。何かお気づきの点がありましたらご指摘お願いいたします。たいしたことはできませんが、よろしければお付き合いくださいませ。
●インストール
Clojure を実行するには Java の実行環境が必要です。M.Hiroi は OpenJDK 21 を使っています。Java のインストールは拙作のページ お気楽 Java プログラミング入門 - はじめに - Java のインストール をお読みください。
Clojure のインストール方法は以下のページで説明されています。
2025 年 5 月時点で、最新バージョンは 2024 年 9 月にリリースされた 1.12.0 です。Ubunts (WSL2) の場合、次のコマンドでインストールすることができます。
curl -L -O https://github.com/clojure/brew-install/releases/latest/download/linux-install.sh
chmod +x linux-install.sh
sudo ./linux-install.sh
●プログラムの実行
シェルでコマンド clj または clojure を入力すると、Clojure の REPL (Read-Eval-Print-Loop) が起動します。
$ clj
Clojure 1.12.0
user=> (+ 1 2 3)
6
user=> (println "hello, Clojure!")
hello, Clojure!
nil
user=>
$
REPL で Clojure のプログラムを入力して簡単に実行することができます。終了する場合は CTRL-D を入力してください。
なお、プログラムをソースファイルに書いて、スクリプト言語のように実行することもできます。
$ cat hello.clj
(println "hello, Clojure!")
$ clj -M hello.clj
hello, Clojure!
$
オプション -M を指定して clj を実行します。一般に、Clojure は拡張子に .clj を用いるのが普通のようです。
●簡単なベンチマーク
Clojure のプログラムは Java 仮想マシン上で動作するので、JIT (Just in Time) コンパイラなどの技術によりプログラムを高速に実行することができます。その実行速度ですが、たらいまわし関数を使って調べてみました。
リスト : たらいまわし関数 (tak.clj)
(defn tak [x y z]
(if (<= x y)
z
(tak (tak (- x 1) y z)
(tak (- y 1) z x)
(tak (- z 1) x y))))
REPL では、(load-file "filename") でソースファイル filename を読み込むことができます。時間計測は関数 time を使うと簡単です。それでは実行結果を示します。(tak 22 11 0) を計算しました。
$ clj
Clojure 1.12.0
user=> (load-file "tak.clj")
#'user/tak
user=> (time (tak 22 11 0))
"Elapsed time: 3010.871979 msecs"
11
user=>
表 : tak(22, 11, 0) の結果
処理系 | 秒 |
Python (ver 3.10.12) | 62.23 |
Ruby (ver 3.0.2p107) | 25.59 |
Lua (ver 5.4.4) | 22.41 |
Gauche (ver 0.9.15) | 21.29 |
ocamlc (ver 4.13.1) | 9.46 |
SBCL (ver 2.1.11) | 4.90 |
Clojure (ver 1.12.0) | 3.01 |
Julia (ver 1.10.5) | 1.84 |
SBCL (最適化) | 1.50 |
Java (ver 21.0.5) | 1.22 |
GCC -O2 (ver 11.4.0) | 1.19 |
Scala (ver 3.3.4) | 1.11 |
ocamlopt (ver 4.13.1) | 1.05 |
- 実行環境 : Ubunts 22.04 (WSL2), Intel Core i5-6200U 2.30GHz
Clojure は SBCL (Common Lisp) よりも高速ですが、GCC, Java, Scala にはかないませんでした。それでも、バイトコードにコンパイルする処理系に比べると、圧倒的に速いですね。Clojure は優れた処理系だと思います。興味のある方はいろいろ試してみてください。
参考文献, URL
- Clojure, (本家)
- Clojure, (日本語訳)
- Clojure - Wikibooks
- Clojure - Wikipedia
権利・免責事項など
『お気楽 Clojure プログラミング超入門』の著作権は筆者「広井誠 (Makoto Hiroi)」が保持します。無断使用や無断転載は禁止いたします。『お気楽 Clojure プログラミング超入門』で作成したプログラムはフリーソフトウェアとします。ご自由にお使いください。プログラムの改造や配布もご自由にどうぞ。その際は、出典を明記してくださるようお願いいたします。
ただし、これらのプログラムは無保証であり、使用したことにより生じた損害について、作者「広井誠 (Makoto Hiroi)」は一切の責任を負いません。また、これらのプログラムを販売することで利益を得るといった商行為は禁止いたします。
Copyright (C) 2025 Makoto Hiroi
All rights reserved.