入門GNU Emacs(11章)

Emacs Lisp

雑感

閉じ括弧の位置がどうにも慣れない。改行して対応する開き括弧の位置と合わせたくなる。

M-x lisp-interaction-mode が便利。いつでもLisp対話モードに移ってC-jで評価が出来る。

基本

Lispの基本要素は関数/変数/アトム

要素 内容
関数 基本要素のリストとして定義
変数 型のない変数
アトム 整数、浮動小数点、文字、文字列、真偽値、シンボル

Lispに特有のこと

  • 関数/変数の単語間の区切りは - を使う。
  • 他の言語では演算子になるものでも関数。
  • 一般文字は ?a のように、文字の前に ? をつける。制御文字は \C-a のように、制御文字の前に \ をつける。
  • 真偽値は 真を t /偽を nil で表現。
  • シンボルは 関数や変数の名前。関数や変数の値ではなく、名前そのものを参照するときに使う。
関数の定義/呼び出し

defun を使って定義

(defun 関数名 (引数1 引数2 ...)
  statement-block)

以下の構文で呼び出し

(関数名 引数1 引数2 ...)
変数の定義(setq/let)

変数の代入(定義)は setq を使うことで実現できる。

(setq var1 value1
      var2 value2
      ...)

let を使うと、それに加えて変数のスコープを制御できる。
statement-blockの中だけで変数が有効になり、グローバル変数と同じ変数名も使える*1

(let ((var1 value1) (var2 value2) ...)
  statement-block)
関数の登録(interactive)

定義した関数を対話的に実行できるようにするには関数の登録が必要*2
関数が引数を必要としなければ "prompt-string" は省略可能。
"prompt-string" は、引数の入力を促す際に使用するプロンプトに表示される文字列。

(interactive "prompt-string")

引数の受け渡し方法が独特で受け取る値によって、prompt-stringの書き方(使う引数コード)が変わる*3

引数コード 受け取る値
b 既存のバッファ名
e イベント(マウスの動作、ファンクションキーの押下)
f 既存のファイル名
n 整数
s 文字列
B 存在しないかもしれないバッファ名
F 存在しないかもしれないファイル名
N 数字(nとの違いがよくわからない)
S シンボル

文字列置換を行うreplace-string関数で以下のような対話を実現したい場合、

Replace string: (文字列の入力)
Replace string (上で入力した文字列) with : (文字列の入力)

interactive は次のように定義する。

(defunc replace-string (from to)
  (interactive "sReplace string: \nsReplace string %s with: ")
  statement-block)

複数の対話入力を実現する場合は、対話用出力文字列を \n で区切って必要分並べる。
直前の入力を次の出力に使いたい場合は、%(引数コード)を出力文字列中の必要な箇所に配置する。

statement-blockの定義(progn/let*/let)

擬似的にstatement-blockを定義するのがprogn。

(progn
  statement-block)

実際にstatement-blockを定義するのがlet/let*。
letは次のような使い方も出来て、値を指定しなければ nil で初期化される。

(let (var1 (var2 value2) var3 ...)
  statement-block)

let*は直前までの式の評価で確定した変数を、次の式の評価で使える点がletと違う。
これを使うと次のようなことが出来る。

(let (var1 value1
      var2 value2
      var3 (+ var1 var2))
  statement)
制御構文(while/if/cond)

while/if はいわゆる while/if の動作をする。
ifの特徴は true-case には 1statement しかかけないため、statement-block を書きたい場合は progn を使う

(while condition statement-block)
(if condition true-case false-block)

switch-case的なことを実現するのが cond。

(cond
  (condition1  statement-block1)
  (condition2  statement-block2)
  ...)

入門 GNU Emacs 第3版

入門 GNU Emacs 第3版

*1:使えるけど、ややこしくなりそうだから、やめとこうっと

*2:コードの中で呼び出す場合は不要なのかな

*3:C の scanf族 みたいな感じなんかな