hitode909の日記

以前はプログラミング日記でしたが、今は子育て日記です

Emacs Lisp入門メモ

下のEmacs Lispを書いたときに学んだメモ.

こういう認識をしている,というだけで,間違ってるかもしれないけど,初学者なので,あまり気にしない.


いろいろと間違っているので,気をつけてください.


関数の定義
(defun myfunc ()
  "This is my function."
  (message "my function was called"))

これで定義して

(myfunc)

で呼べる.

(defun myfunc ()
  "This is my function."
  (interactive)
  (message "my function was called"))

こうすると,M-x myfuncでも呼べる.対話式に使いたいときはinteractiveをつける.

(defun myfunc (a)
  (message a))
(myfunc "hi")

こうすると,引数を渡せる.

変数の定義
(setq x 0)

これは,こういう感じ.

var x = 0;
グローバルな変数の定義
(defvar cute-cursor-interval 0.05
  "Interval")

これは,こういう感じ.

x = 0;

引数の最後は説明を書く.この例ではちゃんと書いてないけど,他の人が書いたのを見ると,しっかり説明が書かれているのが多かった.
defvarでデフォルトの値を設定しておいて,.emacs.elで書き換えると,プログラムの挙動が変わる,という風に使える.
.emacs.elで,

(setq cute-cursor-interval 1)

とすると,オプションが設定されたような状態になって,プログラムの挙動が変わる.

if
(if flag (a) (b))

で,if文を書ける.aはflagが真のとき,bはflagが偽のときに実行される.

when
(when flag (a))

で,flagが真のときaが実行される.

1増やす
(setq x (1+ x))

これでxが1増える.1+というのが,++みたいな感じ.(1- x)もできる.

2増やす
(setq x (+ 2 x))

1以外のときはこういう感じ.四則演算も同じ.

andとor
(and 1 2)
(or 0 1 2)
(and 1 (or 1 2))

こういう感じ.かっこで入れ子にできる.

リストの長さ
(length colors)

すると,colors.lengthみたいな意味になる.

setIntervalする

run-with-timerとcancel-timerで,setIntervalとclearIntervalみたいなことができる.

var f = function(){ };
var timer = setInterval(f, 500);
clearInterval(timer);
timer = null;

これは,こう書ける.

(defun f () )
(setq timer (run-with-timer 0.5 0.5 'f))
(cancel-timer timer)
(setq timer nil)

timerを保持しておかないと,あとでキャンセルしたりできない(たぶん).
timerの初期値をnilにして,キャンセルしたときにnilに設定するようにしておくと,timerがtrueのときは関数が定期的に実行中だと見なしたりできる.

requireできるようにする
(provide 'cute-cursor)

しておくと,(require 'cute-cursor)して使えるようになる.

命名規則

defunしたり,defvarしたりすると,グローバルに宣言されて,describe-functionやdescribe-variableに現れるようになる.
一般的に,他と干渉しないために,変数名の最初にパッケージ名をつける.

(defvar cute-cursor-colors '("red" "green" "blue" "yellow" "purple" "magenta" "cyan")
  "Colors")

みたいな感じ.

今回謎だったこと

cute-cursor-intervalや,cute-cursor-colorsは,ユーザーが変更する可能性があるので,defvarして,外部に公開されるのは正しい.
しかし,内部的に利用しているだけの,cute-cursor-timerという変数もdefvarしたため,内部的な変数が外部に公開されてしまった.
private宣言みたいなことをしたり,クロージャを使って変数を隠蔽したりできるとよいと思ったのだが,そのような方法があるのか分からなかった.
VimScriptには,script localみたいな概念があるらしい.

追記

暮らしの elisp - わからん
id:kitokitokiさんが別解を示してくださったのですが(ありがとうございます),この実装では,lexical-letという関数が使われていました.
これでスコープを制限できるようです.便利そうなので,あとで調べてみようと思います.

追記2

Twitterid:yaottiさんに教えていただきました.上の記述はメンタルモデルをもとに書いていたので,こういう情報を頂けるのはありがたいです!!!.

@hitode909 内部はあんまりよくわからないです./defvarがグローバルになると書いてますが, elispでは変数隠蔽のため(だけでもないけど)に,ある関数でしか使わない変数はletで束縛して,複数の関数で使いたい変数はアクセサメソッドを作るのが常套手段だと思います

Twitter / yaotti: @hitode909 内部はあん

追記3

@cvmatさんに教えていただきました.setqでもdescribe-variableに出るようです.確かに出ました.変数について理解が浅すぎました.

@hitode909 setqでもdescribe-variableに表示されますよ。内部使用かどうかはdocstringの先頭文字が目印です(非強制)。先頭が*だとユーザが変更OK(user-variable-pが真)という感じです Defining Variables - GNU Emacs Lisp Reference Manual

Twitter / cvmat: @hitode909 setqでもdescr

追記4

これを読もうと思います.これを読めば大丈夫そう.
GNU Emacs Lispリファレンスマニュアル: