Emacsを書く前のLisp

Emacs Lispを書き始める前に知っておくと良いLispの基礎について。この記事を読んでもEmacsのスキルは上がりません。あと、話の段取り上、めんどくさい方法から順に説明することがあるよ。

## 対象読者

- むかしの自分
- Emacsを使ってるけどLispについてちょっとは知っておきたいひと

## リスト

`(りんご ばなな みかん)`のように要素を並べたものが**リスト**。データ構造に詳しくないひとは「配列みたいなもの」だと思ってもいい。厳密には連結リスト(linked list)なのでちょっと違ふんだけど、まあ似たようなもの。(あとで説明します)

ちなみに、`()`の中に要素を空白で区切ってならべるリストの書きかたを「S式 (S-expression)」と呼ぶ。Lispのリストは原則としてこの方式で書かれるけど、べつに覚えてなくてもいいです。

### リストによるプログラミング

プログラムとして評価したい式を`(+ 1 2)`のように並べて書く。もちろんこれはリストで、`+`の引数として1, 2を渡すことを意味する。C言語やJavaScriptなどの言語では`1 + 2`のような演算子式が言語構文として用意されるが、Lispでは基本的に区別はない。

そして、`+`はただの函数だ。

### 実行環境

Lispを実行する環境として、Emacsの起動時に`*scratch*`といふバッファが作成されてるはずなので、<kbd>C-x b \*scratch\*</kbd>で移動してみよう。<kbd>C-x C-f hoge.el</kbd>のようにテスト用に`.el`拡張子のファイルを作成してもいい。

また、`M-x ielm`で対話環境を起動することもできる。好きな方を利用しよう。

```el
(+ 1 2)
```

`*scratch*`またはテスト用のファイルで式を実行したいときは、`)`の直後にカーソル移動して<kbd>C-x C-e</kbd>と押してみよう。

![scratchバッファでLispを実行する様子](https://qiita-image-store.s3.amazonaws.com/0/4121/7472b7b7-6169-1866-411b-1a1a1ba3edd1.png)

実行結果は画面下部に表示される。Emacsはリストを解釈して、なんらかの結果を返してくれる。これを**評価**(evaluation)といふ。

### クォート

最初に書いたように`(りんご ばなな みかん)`はリストだ。ところがこれを評価しようとすると、「そんな函数はない」と怒られる。

![(りんご ばなな みかん)を評価した様子](https://qiita-image-store.s3.amazonaws.com/0/4121/5cb6065d-fca4-d61a-e4a3-bab870c20e34.png)

それでは、「プログラムとしてのリスト」と「データの並びとしてのリスト」を区別できない。

ので、データとしてのリストを表現したいときは**クォート**といふ仕組みを利用する。リストをクォートするには`(quote …)`でリストを括ってやる。

```
(quote (りんご ばなな みかん))
```

![(りんご ばなな みかん)を評価した様子](https://qiita-image-store.s3.amazonaws.com/0/4121/9805d622-7314-63b1-f03f-257cb68d76e9.png)

データとしてのリストを、プログラムとして評価し直すこともできる。

![リストをプログラムとして評価する様子](https://qiita-image-store.s3.amazonaws.com/0/4121/5321562c-7e59-e2eb-3abd-2554ee3a00ae.png)

Lispがプログラムをリストとして表現できることには意味がある。Lispで書かれたコードは、プログラムとデータの世界を行ったり来たりすることができる。

### 函数

Emacs Lispでは`defun`で函数定義することができる。

```el
(defun trapezoid (height a b) ; 函数名 (引数リスト)
  "台形の面積を求める."           ; 説明文字列
  (* height (/ (+ a b) 2)))
```

せっかくなのでPHPで、まったく同じコードを書いて比較してみる。

```php
/**
 * 台形の面積を求める.
 */
function trapezoid($height, $a, $b)
{
    return $height * ($a + $b) / 2;
}
```

`defun`の中では、`height`, `a`, `b`といふ**変数**が利用できる。ここで「変数」といふ概念が初めて現れたが、Lispの式の中に現れる文字の並びを **シンボル** と呼ぶ。ここでは`trapezoid` `height` `a` `b`がシンボルだ。シンボルを評価すると、変数の値になる。ここはLisp以外の言語と同じっすね。

PHPのコードでは演算子の結合度の違ひがあるので`($a + $b)`は括弧で括らないといけないのでバグの温床になるが、Lispでは二項演算子を利用しないので問題ない——と強弁すれば主張できないことはないけど、実際は算数の授業とかで習ってきた書きかた(中置記法)の方が馴染みがあるし、ほかの言語で実装されたアルゴリズムを実装するときに困らないので無理に慣れようとする必要もない。

最後に、返り値について。CやPHPなどのように`return`のようなものはない。リストの最後に評価された値が返される。

幸ひにもEmacsには中置記法で書くこともできる。

```el
(defun trapezoid (height a b) ; 函数名 (引数リスト)
  "台形の面積を求める."           ; 説明文字列
  (string-to-number
   (calc-eval "$ * ($$ + $$$) / 2" nil height a b)))
```

`nil`については後で説明する。`$` `$$` `$$$`は変数のプレースホルダで、それぞれ第一引数、第二引数、第三引数… と増えていく。(もちろん10個引数があれば`$$$$$$$$$$`になるのは難点…)

## Lispプログラミングに役立つモード

### show-paren-mode

ここまでコピペせずに手で書き写してくれた型がいらっしゃるかはわからないが、`()`の対応の把握に四苦八苦したりはしなかっただろうか。

そんなときは、そんなときじゃなくても、`show-paren-mode`は有効にしておくといい。

![emacs-show-paren-mode.gif](https://qiita-image-store.s3.amazonaws.com/0/4121/c74ddc2f-61c9-b5de-1d0b-080e77602d21.gif)

カーソル位置にある括弧の対応関係がわかりやすくなるので、Lispじゃない言語でのコーディングでも便利だが、Lispでは特に重要度が高いので常時onにしておくと良いだろう。

自分の`~/.emacs.d/init.el`か`~/.emacs`ファイルに一行書いておくだけでいい。

```init.el
(show-paren-mode 1)
```

余談だが、一部の人の間では始まり括弧`(`を「カッコ」、閉じる括弧`)`を「コッカ」と呼ぶ文化がある。 *文化…?*

### eldoc

Emacsには、入力中の函数がどのような引数を取るのか、あと現在どの引数を入力中なのかを視覚的に把握するための機能が付いてる。

![emacs-eldoc.gif](https://qiita-image-store.s3.amazonaws.com/0/4121/e0999661-2ca1-da6c-bdff-377016bf6918.gif)

これも、`init.el`に一行書くだけでいい。

```init.el
(add-hook emacs-lisp-mode-hook 'turn-on-eldoc-mode)
```

### そのほか

標準でインストールはされてないけど、ParEditは非常におすすめ度が高い。慣れると非常にたやすくリストを操作できるようになる。日本語の[ParEdit チュートリアル](http://www.daregada.sakuraweb.com/paredit_tutorial_ja.html)があるので、習熟するにはあまり手間はかからないだろう。

## 変数

話が脱線してしまった。脱線する前には函数定義の話で、引数として渡されてきた変数についても言及した。

### 一時変数

`let*`式を利用すると、ローカルでのみ有効な変数を作ることができる。

```el
(let* ((a (+ 2 3 4))
       (b (* a a a)))
  (insert (format "\nresult = %d, %d" a b)))
```

変数が有効なのは`(let* …)`で囲まれた中だけで、実行が終了すると変数`a` `b`は参照できなくなる。

このあたりから「どこでスペース何個ぶんインデントすればいいんだ…」と途方に暮れはじめる頃なのだけれど、実際のところEmacsでは`TAB`または`C-i`を押せば勝手にいい感じにしてくれる。「そろそろ位置を調節したいな」って気分になってきたらポンとキーを押すだけでいい。それだけ。

### 変数の変更

変数の値は`set`で変更することができる。`(set symbol value)`のような式を評価すると、`symbol`のシンボルを`value`に束縛することができる。

用語として出てきた**束縛**(bind)なのだけれど、**代入**(assign)と同じだと思って問題ない。

だが待ってほしい、シンボルを引数として渡さなければいけないのだ。シンボルはそのまま書くと変数として評価されてしまふので、クォートして渡さなければいけない。つまり、次のように！

```el
(let* ((x "a"))
  (insert x)
  (set (quote x) "b")
  (insert x))
```

いや、さすがにいちいち`(quote v)`とか書くのはめんどくさいだろ… ってことで、もっと簡単な方法がある。

```el
(setq x "b")
```

これでいい。むしろ、ふつうは`set`よりも`setq`の方が頻繁に利用される。

### 特別な値

Lispで一番の特別な値として`nil`がある。この値にはいくつかの役割があるのだけれど、いちばんわかりやすいのは**偽値**だろう。

```el
(eq 1 2)  ;=> nil
(eq 2 2)  ;=> t
(not t)   ;=> nil
(not nil) ;=> t
```

せっかくなので、ついでに`if`も紹介しておく。

![Lispで奇偶判定してる様子だよっ](https://qiita-image-store.s3.amazonaws.com/0/4121/2fd705fc-4f42-d4ec-bab1-65b86f4333af.png)

C言語などで三項演算子(条件演算子)を使ったことがあれば、まったく同じものだと気付くだろう。

### クォート

`(quote x)`とか書くのは実際めんどくさい。ので、省略記法がある。

```el
(eq (quote Python) 'Python) ;=> t

(equal '(りんご ばなな みかん)
       (quote (りんご ばなな みかん))) ;=> t

(eval '(+ 1 2 3)) ;=> 6
```

Lispに触れずにEmacsのカスタマイズをしてきたなら、こちらの記法は馴染みがあるかもしれにあ。実際こちらの方がよく利用する——といふよりも、ふつうは`setq`で`set`はあまり利用しない。

余談だけれど、日本語では`setq`は「せっとく」と読まれる。[うそじゃないよ](http://blog.bugyo.tk/lyrical/archives/1090)、[竹内先生もそう言ってるよ](https://books.google.co.jp/books?id=LnQaBwAAQBAJ&pg=PT237&lpg=PT237&dq=setq+%E8%AA%AC%E5%BE%97&source=bl&ots=5Pgv7lfpCj&sig=JTiMoJPHttsuB7QiCKlHWMkLC0I&hl=ja&sa=X&ved=0ahUKEwirmLGro8jMAhWCF5QKHcdtCeUQ6AEIIjAB#v=onepage&q=setq%20%E8%AA%AC%E5%BE%97&f=false)。 *Emacsを説得するんじゃ。*

## リスト

**リスト**はEmacsでもよく利用されるデータ構造である。その根本にあるのはとてもシンプルなアイディアだけれど、とても複雑なデータ構造をも表現することができる。

### リストを作るには

Lispでデータとしてのリストを作るには、いくつかの方法がある。

* リストをクォートする
* `list`函数で書く
* コンスセルを組み立てる

**リストをクォートする方法**はいままで書いてきた通りで、`(quote (1 2 3))`または`'(1 2 3)`と書きます。<code>`(1 2 3)</code>と書くこともできるけれど、これはもっと別の機能があるので後で紹介する。

**`list`函数で書く**方法はとてもおてがる。`(list 1 2 3)`と書くこともできるし、以下のように変数を利用することもかんたんにできる。

```el
(let ((a 2)
      (b 5)
      (c 6))
  (quote (a b c)) ;=> '(a b c)
  (list a b c))   ;=> '(2 5 6)
```

**コンスセルを組み立てる**方法については次に書く。

### 空リストとは

「<ruby>空<rp>(</rp><rt>くう</rt><rp>)</rp></ruby>とは何ぞ？」 ——とは禅問答のような問だが、<dfn><ruby>空<rp>(</rp><rt>から</rt><rp>)</rp>リスト</ruby>とはいったい何者なのか。

わからないときはEmacsさんに質問だ。

![M-x ielmで(quote ())を評価するとnilが現れるのだ](https://qiita-image-store.s3.amazonaws.com/0/4121/fc7a1d13-d42f-73df-4df8-5af425582488.png)

なんと、リストだと思ったら`nil`が現れてしまった。嘘だと思ったら自分で`(eq nil '())`とか評価してみてね。

### セル

Lispでの「リスト」とは、いはゆる**連結リスト**、それも**単方向リスト**にあたる。C言語の入門の講義などで実装させられたことがあるかもしれないが、Lispでははじめから組み込みで、しかも簡単に利用できる。

その根幹にあるのは「セル」と呼ばれるデータ構造で、歴史ある<sub>実際には大した意味がない</sub>用語を伴って「コンスセル」とも呼ばれる。

```el
;;   CAR部  CDR部
(cons  'a    'b)
```

`cons`はただの函数で、引数として渡した二つの要素を持つセルを作り出す。前の方を「<ruby>CAR<rt>カー</rt></ruby>」、後の方を「<ruby>CDR<rt>クダー</rt></ruby>」と呼ぶ。これは変な名前だが歴史的経緯の産物で、現代においては特に意味はない。

### セルからリストへ

さて、空リストは`nil`だと言ったが、一要素のリストとは何か？ 解答を書いてしまふと次の通りだ。

```el
(cons 'a nil)

;; 本当にそうなのか? 自分で動かして試してみよう。
(equal (list 'a)
       (cons 'a nil))

(equal (quote (a))
       (cons 'a nil))
```

いままでいくつか紹介してきた方法は、`cons`函数を使っても表現することができる。また、リストの中で`(a . b)`のように`.`を付けて書くと、`cons`のように2要素が組になったセルを作ることができる。これを「**ドット<ruby>対<rt>つい</rt></ruby>** (dotted pair)」と呼ぶ。

なんと以下の式は、すべて同じリスト`(a b c)`として評価される。

```el
(cons 'a (cons 'b (cons 'c nil)))
(cons 'a (list 'b 'c))

(quote (a . (b . (c . nil))))
(quote (a b c . nil))
(quote (a . (b c)))
(quote (a b c))

(list 'a 'b 'c)
'(a b c)
```

### リストの皮剥き

データを並べたからには、取り出したくなるだろう。セルのCAR部とCDR部を取り出すのは、そのまま`car`と`cdr`だ。

```el
(car '(a b c))             ;=> a
(cdr '(a b c))             ;=> (b c)
(car (cdr '(a b c)))       ;=> b
(cdr (cdr '(a b c)))       ;=> (c)
(car (cdr (cdr '(a b c)))) ;=> c
```

実用的なプログラムを書くのにいちいちこんなことをやってたのではノイローゼになりかねない！ 

もちろん、もっと便利な函数はいくつもある。

```el
(first '(a b c))  ;=> a
(second '(a b c)) ;=> b
(third '(a b c))  ;=> c
(fourth '(a b c)) ;=> nil
(fifth '(a b c))  ;=> nil

(nth 0 '(a b c)) ;=> a
(nth 1 '(a b c)) ;=> b
(nth 2 '(a b c)) ;=> c
(nth 3 '(a b c)) ;=> nil
(nth 4 '(a b c)) ;=> nil
```

`first`と`nth`は数がずれてることには注意しよう。`nth`の方はC言語の配列と同じだと思っておけばいい。

### 連想リスト

リストはとてもシンプルなデータ構造だけれど、前の項目のように数字でアクセスするだけじゃなく、任意の値をキーにして中身を取り出すこともできる。これは、ほかの言語では「**連想配列**(associative array)」などと呼ばれるが、それに似た使いかたができるので「**連想リスト**(association list)」と呼ばれる。

```el
(assoc 'hoge '((hoge . 1) (fuga . 2))) ;=> (hoge . 1)
(assoc 'fuga '((hoge . 1) (fuga . 2))) ;=> (fuga . 2)
```

`assoc`函数では、引数として渡された値をキーにして、リストの各要素のCARが一致すれば、そのドット対を返す。値が欲しければ、その外側をさらに`cdr`で囲ってやればいい。

データ構造について興味関心があれば、連想リストのメリットとデメリットについて想像してみると良いですね。<sub>今回は紹介しないけど、Emacs Lispにはハッシュテーブルもあるよ…</sub>

### 連想リストと応用

`assoc`に似た函数に`assoc-default`がある。こちらのおもしろい点として、比較函数を指定できることがある。(また、`assoc`はドット対を返すが`assoc-default`はCDR部だけを返す)

`string-match`は正規表現パターンにマッチしなければ`nil`を、マッチしたらその位置を返す函数だ。

```el
(string-match "AB?C+D" "ACCCD") ;=> 0
(string-match "AB?C+D" "CCCD")  ;=> nil
```

この二つを組合せると、どうなるか。

```el
(assoc-default "/path/file.md"
               '(("\\.txt\\'" . my-text-mode)
                 ("\\.rb\\'" . my-ruby-mode)
                 ("\\.md\\'" . my-markdown-mode))
               'string-match)
```

`"/path/file.md"`の部分を`"/path/file.rb"`や`"/path/file.py"`のように変更すると、どのように動作が変るか確認してみよう。

さて、この仕組みは実際にEmacsがファイル名からメジャーモードを決める仕組みそのものだ。

### 属性リスト

属性(attribute/property)とは、あるものの持つ共通した性質のことで、哲学的な説明については[属性 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%B1%9E%E6%80%A7)を読んでいただくとして、HTMLの「属性」やJavaやPHPなどのクラスの「プロパティ」と同じような概念だと思っておいて良い。

果物の値段と出荷日のリストをむりやりHTMLで表現すると、こうなるだろうか。(おそらく、このあとJavaScriptで処理されるのだろう…)

```html
<ul class="fruits">
   <li class="fruit" data-price="250" data-ship-date="2015-10-21">りんご</li>
   <li class="fruit" data-price="300" data-ship-date="2016-01-14">みかん</li>
   <li class="fruit" data-price="300" data-ship-date="2016-03-08">ばなな</li>
</ul>
```

Lispでは次のような単純な形式のリストで表現することができる。ちなみに`:abc`のように`:`から始まるシンボルはEmacs Lispでは「定数」として予約済みで、クォートせずに利用することができる。

```el
(list
 '(:果物 "りんご" :値段 250 :出荷日 "2015-10-21")
 '(:果物 "みかん" :値段 300 :出荷日 "2016-01-14")
 '(:果物 "ばなな" :値段 300 :出荷日 "2016-03-08"))
```

そして、そのようなときに利用できるのが`plist-get`函数だ。属性のキーと値が交互に並んだリストから「いい感じ」に値を取り出してくれる。

```el
(let ((apple '(:果物 "りんご" :値段 250 :出荷日 "2015-10-21")))
  (format "%s：%d円 (%s 発送)"
          (plist-get apple :果物)
          (plist-get apple :値段)
          (plist-get apple :出荷日)))
;=> "りんご：250円 (2015-10-21 発送)"
```

ここまでに、ほかの言語の連想配列に相当するものとして、「連想リスト(association list)」を紹介した。しかし実際のところ、RubyやPHPなどの言語では属性リストに近い用途で`Hash`クラスや(連想)配列が利用されることがある。

## このあとのLisp

古い本なのでもう既に新品では売ってないのだけれど、[リスト遊び -- Emacs で学ぶ Lisp の世界](http://www.mew.org/~kazu/doc/book/list.html)ではこの記事と同様にEmacs Lispを通じてLispを学ぶことができる。(@kazu_yamamoto先生におかれましては電子書籍でも良いので再販していただきたく、何卒、何卒…)

また、[魔法言語 リリカル☆Lisp](http://lyrical.bugyo.tk/)はインタラクティブにLispを学ぶことができる素晴らしいゲームだ。ふざけた名前のように見えるかもしれないけれど内容は本当に良くて、私はこのゲームのせいでLispに興味を持ってしまった。ただし、Emacs Lispとは仕様がちょっと異なる点については注意。

さらにそのあとについては、インターネット上にもいろいろなヒントがあるので読んでみたり、Emacs Lispパッケージを書いてみたり、あるいはほかのLispを触ってみるのも良いかもしれない。

私は書籍では「Scheme手習い (The Little Schemer)」が大好きなのだけれど、これは人によって感想の差が激しくて、**のめりこむ**か**うんざりする**かの両極端のように感じる。本屋か図書館で何章か読んでみてから購入した方が良いだろう。

この記事のタイトル通りにEmacs Lispについて学びたい型は、英語だけれど[GNU Emacs Lisp Reference Manual](https://www.gnu.org/software/emacs/manual/html_node/elisp/index.html)を読めばなんとかなる。また、日本語の書籍では[Emacs Lispテクニックバイブル](http://www.amazon.co.jp/gp/product/4774148970/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4774148970&linkCode=as2&tag=wx310kflashca-22)<img src="http://ir-jp.amazon-adsystem.com/e/ir?t=wx310kflashca-22&l=as2&o=9&a=4774148970" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />があり、(現在では多少事情が異る箇所はあるものの)Emacs固有の技術的な事情についてかなり詳細に記述されてるのでおすすめ。

そのほか[Emacs Lisp の情報源 - Qiita](http://qiita.com/ongaeshi/items/3f6415732867d2ba0e27)にまとめられてる。


<!-- ## なぜLisp

大学生の頃の私のようなアレゲな若者は「[ハッカーになろう (How To Become A Hacker](http://cruel.org/freeware/hacker.html)」や「[普通のやつらの上を行け (Beating the Averages)](http://practical-scheme.net/trans/beating-the-averages-j.html)」、そして「[技術野郎の復讐 (Revenge of the Nerds)](http://practical-scheme.net/trans/icad-j.html)」のような古文書を読んでは意識を高めて、やがて忘れ去っていった。

そして、気付いたら現在の私の手元にはEmacsがあった。 -->