スキップしてメイン コンテンツに移動

Emacs Lispのススメ

概要



私の受ける印象では,Emacs Lispを敬遠している人が多すぎる.多くの場合,この理由は,(1) Lispが嫌い,(2) Emacsが嫌い,のいずれかである.後者は思想の違いなのでどうしようも無いが,前者の理由で使わないのであれば,損をしていると私は考える.



ここでは,私がEmacs Lispを実際に利用する場面を,ケーススタディとして示す.Lispが嫌いな方が退屈しないよう,Lispの構文については触れない.


Emacs Lispを実行するには



まず,Emacs Lispを実行する方法を知らなければならない.手っ取り早く実行する方法として,次の2種類の方法がある.この他にも数種類の方法があるが,ここでは省略する.


*scratch*バッファを使う



Emacsを引数なしで起動すると,*scratch*バッファが開かれる.このバッファで\C-jと入力すると,カーソルの直前にあるLispを実行する.



例えば次のコードは,hogeと出力するものである.



(message "hoge")


この「)」の次にカーソルを合わせて\C-jを入力すれば,カーソル位置に"hoge"と出力される.



(message "hoge")
[ここにカーソルを置いて\C-jと入力]
=> "hoge"

eval-last-sexp関数を使う



上記のコードにて,上記と同様「)」の次にカーソルを合わせる.そして,\C-x\C-eと入力すると,直前のLispを実行する.



入力シーケンス \C-x\C-eは,M-x eval-last-sexpと同様.上記と同様,カーソル位置の手前にあるLispを評価する. *scratch*バッファとの違いは,実行結果がミニバッファに表示される点,一般のファイル(*scratch*バッファ以外)でも実行できる点,である.


ケーススタディ


簡単な計算をする



Emacs Lispを用いると,簡単な四則演算が可能.



例えば,次のLispは1日の秒数を計算する.



(* 60 60 24)
=> 86400


また,あるファイルに次のような数値の羅列が保存されているとする.



34
42
...
56


これらの数値の合計を求めるには,前後にLispを加えれば良い.



(+
34
42
...
56
)


勿論,複雑な計算も可能.次は,1から1000までの数値の合計を計算する.ちなみに,1からNまでの合計はN*(N+1)/2.



(/ (* 1000 (+ 1000 1)) 2)
=> 500500


少数が含まれれば浮動小数点演算,整数のみであれば整数演算となる.



(/ 10 3)
=> 3
(/ 10.0 3)
=> 3.333333333

文字列を自動生成する



例えば,C言語で次の定義文を書くとする.



#define HOGE0 100
#define HOGE1 101
#define HOGE2 102
#define HOGE3 103


4行であれば大した問題ではないが,これが100行になったら,あるいは頻繁に行数が変わるとすれば,さすがに自力で書くのはしんどい.



ここでEmacs Lispが活躍する.次のEmacs Lispで,上記の定義文を生成できる.



(let ((i 0))
(while (< i 4)
(insert (format "#define HOGE%d %d\n" i (+ 100 i)))
(setq i (+ i 1))))


かなりラフに説明すると,次のようになる.(1) letでローカル変数iを定義.(2) whileでiが0から3までループ.(3) insertでカレントバッファに1行ずつ出力.(4) setqでiをインクリメント.



この方法の良いところは,Cのコードを書いているエディタ上に自動化のコードを書くことができ,その場で実行できるところにある.



これだけでは意味がわからないので,Emacs Lispを使用しない場合を例に示そう.コードを生成自動するには,jotやseqを使う,またはrubyやperlなどのスクリプトを組む,といった方法がある.これらの方法には,スクリプトファイルが増える,という問題点がある.私も経験があるが,スクリプトファイルが散乱すれば,管理することが困難になる.何のスクリプトファイルが何をするものであったのか,作者でも時間が経てば忘れてくるのだ.



一方,Emacs Lispであれば,Cのソースコード内に記述できる.さらに,次のようにCの構文でコメントアウトしておく.



/*** Cソースファイル ***/
/*
(let ((i 0))
(while (< i 4)
(insert (format "#define HOGE%d %d\n" i (+ 100 i)))
(setq i (+ i 1))))
*/


こうすることで,(1) 新たにスクリプトファイルが増えることなく,(2) 必要な箇所に必要なEmacs Lispのコードを配置し,(3) Cのコンパイルも問題なく通す,ことができるのである.



ちなみに,おわかりだと思うが,上記コードは,次のように4を100に変更することで,100行の出力が可能.



/*
(let ((i 0))
(while (< i 100)
(insert (format "#define HOGE%d %d\n" i (+ 100 i)))
(setq i (+ i 1))))
*/