1 Emacs Lisp を少し勉強した gblog
Emacs Lisp のコードを読むときに知らなくて困った(多分)基本的な所をメモ.
困ったときに調べたものだけメモしているので,網羅はしてない.
1.1 コンスセル
「CARスロットおよびCDRスロットと呼ばれる 2つのポインタから成るオブジェクトです。」らしい.
「各スロットは、任意のLispオブジェクトを指すことができます。」
ドット記法とかで表現する.
(A . B)
と書くと,A がCARスロット,B がCDR スロット参考ページ:
GNU Emacs Lispリファレンスマニュアル: Cons Cell Type
1.2 cons obj1 obj2
obj1 とobj2 から成るコンスセルを作る関数.
(cons 1 2) => (1 . 2)
1.3 リスト
リストはコンスセルの入れ子構造.
(1 2 3)
と表示する.この実態は,CARスロットが1, CDR スロットが(2 3) のコンスセル.
2と3 が要素のリスト(2 3) の実態は CARスロットが2, CDR スロットが(3) のコンスセル
3だけが要素のリスト(3) の実態は CAR スロットが3, CDR スロットが空リストの()
ドット表記だと(1 . (2 . (3 . ())
(cons 1 (2 3)) => (1 2 3)
(cons 1 ()) => (1)
また,空リスト() はnil とも書く
つまり,
(cons 1 nil) => (1)
1.4 関数car, cdr
コンスセルのCAR スロットを取り出すのがcar 関数,CDR スロットを取り出すのがcdr 関数.
リストに適用すると,以下のような感じ.
(car '(0 1 2)) => 0
(cdr '(0 1 2)) => (1 2)
1.5 シングルクォートは何?
car やcdr の例では'(0 1 2) とリストの前に「'」がついている.
これは,リストを評価しないようにするためのものらしい.
リストを評価するとは,リストのCAR スロット(第一要素)を関数名,第二引数以降を関数の引数として,計算するということ.
Lisp は(0 1 2) とだけ書いて実行すると,0 を関数名,1 を第一引数,2 を第二引数として計算しようとするらしい.
これをせずに,リストとしてそのまま置いておくために,シングルクォートをつける.
関数名や変数名の前に「'」をつけるのも同じ理由のようである.
参考ページ:
Programming in Emacs Lisp: List Processing
また,別の説明で,おそらくより厳密な説明が以下のリンクにある.
Emacs Lisp
これをちゃんと理解するためには,シンボルというものを理解しないといけないらしい.
また,シンボルなるものの構造については以下のリンクが詳しいと思う.
GNU Emacs Lispリファレンスマニュアル: シンボル
このあたりの理解は今後の課題.
1.6 let
ローカル変数を定義して,最後のリストを評価する.
(let (ローカル変数の定義のリスト) フォーム1 … フォームn)
ローカル変数の定義のリストは以下の構文
((ローカル変数名1 初期値1) ローカル変数名2 … (ローカル変数名n 初期値n))
(ローカル変数名1 初期値1) と言うリストは,ローカル変数名1 が初期値1 で初期化することを示す.
一方,ローカル変数2 とだけ書いていると,ローカル変数2 はnil で初期化する.
フォームとは,Emacs Lisp のコードと思えばいいのかな?
let 全体の戻り値は,最後のフォーム(フォームn) の戻り値になる.
例:
(let ((x 3)) x) => 3
(let ((x 3) (y 2)) x y) => 2 ;; 最後のフォームがlet の戻り値になる
(let ((x 3) (y 2)) (+ x y)) => 5
(let ((x 3) y (z 4)) (list x y z)) => (3 nil 4) ;; (list x y z) はx y z を要素とするリストを返す
1.7 スペシャルフォーム(special form) とマクロ
普通,リストの形式で書いて実行すると,全てのリストが評価される.
しかし,例外があるらしく,それがspecial form というらしい.
先のlet はその一つ.
(let ((x 3) (y 2)) (+ x y)) の(x 3) はリストだが,これを関数として評価していない(したらx なんて関数はないとエラーが出るはず)
一方,一番後ろの(+ x y) は評価されている.
このように,let の引数に関しては,一番後ろしか評価しない,ということになっているようである.
他にも,値を変数に代入するsetq などがそうらしい.
また,スペシャルフォームという言葉を調べていると,マクロという言葉もよく見かける.
マクロは,ユーザー定義のスペシャルフォームらしい.
参考ページ:
スペシャルフォームとマクロ - by shigemk2
1.8 dolist
実は,このブログの内容は,dolist のサンプルコードがわからなくて調べだしたのがきっかけ.
つまり,今回のブログはここがゴール.
dolist もlet のようにスペシャルフォーム.
構文は以下.
(dolist (ローカル変数 リスト [戻り値]) フォーム1 … フォームn)
リストの要素を一つずつローカル変数に代入してフォーム1 からフォームn の処理を繰り返す
python とかでいうforeach 的なやつ.
戻り値を設定しないと,dolist の戻り値はnil になる.
また,戻り値に未定義の変数は使えないので,予め定義する必要がある.
例:
(let ((sum 0)) ;; 戻り値に使う変数を定義
(dolist (x '(1 2 3) sum)
(setq sum (+ x sum)))) => 6
--
My Emacs Files At GitHub
0 件のコメント:
コメントを投稿