by shigemk2

当面は技術的なことしか書かない

Emacs Lisp

レキシカルスコープを使う

elispでレキシカルスコープを使うにはlexical-letを使う。 (defun f1 (func) (let ((v 'internal)) (funcall func))) (lexical-let ((v 'external)) (f1 (lambda () v))) ; => external (defun f2 (func v) (funcall func v)) (let ((v 'external)) (f2 (lam…

ダイナミックスコープとレキシカルスコープ

実行するまで分からない動的なスコープを ダイナミックスコープという。字面を見てスコープが分かるスコープをレキスカルスコープという。Emacs Lispはダイナミックスコープであり、 Common Lispはレキシカルスコープという。下記はダイナミックスコープの例…

リスト要素を更新 削除する

add-to-listより短く、また汎変数も利用可能。 (setq l nil) (push 1 l) ; => (1) (macroexpand '(push 1 l)) ; => (setq l (cons 1 l)) l ; => (1) (push 2 l) ; => (2 1) l ; => (2 1) (cons 2 l) ; => (2 2 1) l ; => (2 1) (pushnew 2 l) ; => (2 1) (ma…

インクリメント デクリメント

;; 変数のインクリメント デクリメント (setq a 0) (incf a) ; => 1 (macroexpand '(incf a)) ; => (setq a (1+ a)) a ; => 1 (incf a 2) ; => 3 (macroexpand '(incf a 2)) ; => (setq a (+ a 2)) a ; => 3 (decf a) ; => 2 (macroexpand '(decf a)) ; => (…

汎変数

setqでは代入値左辺(リストのcar)の書き換えは出来ないが、 この汎変数を書き換えるにはsetqではなくsetfを使う。 ;; リストの値の変更 (setq l '(1 2 3)) ;; 同じことをsetqでしてもエラー (ignore-errors (setq (car l) 10)) l ; => (1 2 3) (setf (car l)…

マクロ定義を拡張する

;; defmacroではリスト分解機能はない (defmacro for2 (spec &rest body) (declare (indent 1)) (let ((limit (gensym))) (destructuring-bind (var start end) spec `(let ((,var ,start) (,limit ,end)) (while (<= ,var ,limit) ,@body (setq ,var (1+ ,v…

関数定義を拡張する

Common LIspの拡張関数defun*を使うと、 &optional デフォルト引数 &key キーワード引数 リスト分解機能が使えるようになる。 ;; 拡張されたデフォルト値 (defun* test-default (a &optional (b 2) (c 3 c-avail)) (list a b c c-avail)) (test-default 1) ;…

destructuring-bindはデフォルト値やキーワード引数も使える

(destructuring-bind (&optional a (b 2)) '(1) (list a b)) ; => (1 2) (destructuring-bind (a &rest b) '(1 2 3) (list a b)) ; => (1 (2 3)) (destructuring-bind (&key a b) '(:a 10 :b 20) (list a b)) ; => (10 20) P193Emacs Lispテクニックバイブル…

Common Lisp リスト構造を分解する

(setq l `(1 (2 3 (4)) 5)) ;; リスト構造を分解するのは面倒 (let* ((a (car l)) (l2 (cadr l)) (b (car l2)) (c (cadr l2)) (d (car (nth 2 l2))) (e (nth 2 l))) (list a b c d e)) ; => (1 2 3 4 5) ;; リスト構造の形を与えるだけで楽々分解 (destructu…

評価回数と変数補足

(defmacro for-wrong1 (var start end &rest body) (declare (indent 3)) `(let ((,var ,start)) (while (<= ,var ,end) ,@body (setq ,var (1+ ,var))))) ;; 123nil ;; でもendが関数だったら、副作用も一緒に繰り返される ;; そして評価回数は4回となる。 …

マクロを定義する

以下のコードをマクロを使って書くことにする。 (if t (progn (setq a 1) (message "%s" a))) ; => "1" (if nil (progn (setq a 1) (message "%s" a))) ; => nil マクロを定義するにはdefmacroを使う (defmacro my-when (condition &rest body) `(if ,condit…

マクロの定義のステップ

マクロにしたいコードを発見する 「関数名、変数名の命名」に従ってマクロ名をつける マクロを使うとどう書けるのかを思い描く 可変部分を引数にする defmacroでマクロ定義を記述する テストをする P181Emacs Lispテクニックバイブル作者: るびきち出版社/メ…

バッククォート

特定の記法により、式の評価値を産め込むことが出来る。 ;; ,と@がなければ普通のquoteと同じ `(1 2 3) ; => (1 2 3) ;; ,の後に式の評価値を埋め込む `(1 ,(+ 1 1) 3) ; => (1 2 3) `(foo ,(list 'bar) baz) ; => (foo (bar) baz) ;; ,@の後にリスト展開を…

マクロとマクロのタイプ

スペシャルフォームとマクロ - by shigemk2マクロとは、S式からS式への展開規則である。 フォームが評価されるとき、またはバイトコンパイルされるとき、真っ先にマクロが展開される。 マクロによって展開されたコードにマクロが含まれていたら、それも再び…

S式から正規表現を作成する

実行結果を見たら分かるように、Emacsの正規表現は大量の\に汚染されて とても見れたものじゃない。というとで、rxというミニ言語マクロを利用してS式から正規表現文字列に変換する。 ;; 文字列お指定すると文字列そのものにマッチする正規表現を作成する (r…

文字列の集合にマッチする正規表現を作成する

regexp-optを使い、文字列の集合にマッチする正規表現を作成する。 第二引数tを使うと、\(......\)でグルーピングされる。 ;; prognがprog1にマッチする正規表現 (setq re (regexp-opt '("progn" "prog1") t)) ; => "\\(prog[1n]\\)" (string-match re "prog…

エラー時の処理を記述する

condition-caseを使う (condition-case nil "Normal case" (errr "Error!")) ; => "Normal case" (condition-case nil (delete-file "file-not-found!") (file-error "File-error!")) ; => "File-error!" (condition-case err (delete-file "file-not-found"…

エラーを抑止する

ignore-errorsを使う ;; substringでのエラー抑止 ;; (substring "f" 3) (args-out-of-range "f" 3 1)というエラーが出る (ignore-errors (substring "f" 3)) ; => nil P172Emacs Lispテクニックバイブル作者: るびきち出版社/メーカー: 技術評論社発売日: 2…

関数のプログラミング

;; 無名関数を変数に代入する (setq twice (lambda (x) (* x 2))) ; => (lambda (x) (* x 2)) (funcall twice 10) ; => 20 ;; 名前付き関数をfuncallで呼ぶ (+ 3 4) ; => 7 (funcall '+ 3 4) ; => 7 ;; 変数にシンボルを指定する例 (setq op '*) (funcall op…

ハッシュテーブル

ハッシュテーブルとは、高速にデータの関連付けをするデータ構造である。 キーと値を関連付けたりキーか値を取り出したりすることが簡単にできるそうな。 ;; ハッシュテーブルを作成する (setq hash (make-hash-table :test 'equal)) ; => #s(hash-table siz…

連想リスト

連想リストとは、コンスセルを要素とするリストで、キーと値がコンスセルのペアになっている ;; 単純な連想リスト (setq alist '((one . 1))) ; => ((one . 1)) ;; ペアの追加 (add-to-list 'alist '(two . 2)) ; => ((two . 2) (one . 1)) alist ; => ((two…

M-x apropos

Emacsに組み込まれている検索エンジンで、シンボル名の一部を入力すると、 それにマッチするシンボル(関数名、変数名、フェイス名)を列挙する。P157Emacs Lispテクニックバイブル作者: るびきち出版社/メーカー: 技術評論社発売日: 2011/11/26メディア: 単行…

文字列からシンボルを作成する

;; abracadabraが未登場のシンボルと仮定すると (intern-soft "abracadabra") ; => nil (intern "abracadabra") ; => abracadabra ;; internにより既存シンボルとなったので、intern-softでもみつかる (intern-soft "abracadabra") ; => abracadabra (symbol…

型変換

(string-to-number "100") ; => 100 ;; N進数→数値 (string-to-number "100" 16) ; => 256 (string-to-number "1011" 2) ; => 11 (number-to-string 1000) ; => "1000" (number-to-string 1000.01) ; => "1000.01" (format "%s %s" 1000 1000.01) ; => "1000…

ソート

;; 数値のソート (setq l '(3 5 2 4 7 8)) ; => (3 5 2 4 7 8) ;; 昇順(比較関数にはクオートをつけること) (setq l (sort l '<)) ; => (2 3 4 5 7 8) ;; 降順 (setq l (sort l '>)) ; => (8 7 5 4 3 2) ;; こちらは破壊的にやってる l ; => (8 7 5 4 3 2) ;…

同一要素で構成されるベクタを作成する

(make-vector 5 nil) ; => [nil nil nil nil nil] (make-vector 5 0) ; => [0 0 0 0 0] (make-vector 5 "foo") ; => ["foo" "foo" "foo" "foo" "foo"] 同一なので、各要素はeqの関係にある。P151Emacs Lispテクニックバイブル作者: るびきち出版社/メーカー:…

シーケンスのコピー

シーケンスとは、リスト、ベクタ、文字列の総称のことで、 破壊的メソッドを使用しかつオリジナルを残すにはcopy-sequenceを使う ;; 破壊的操作をする関数でオリジナルを保存する例 (setq l '(4 3 8 1)) ; => (4 3 8 1) ;; 破壊的操作! (delq 8 (copy-sequen…

ウィンドウ構成の保存、復元

1. M-:で(setq wc (current-window-configuration))みたいなのを実行し、構成を保存する 2. M-:(set-window-configuration wc)で、構成を復元できる。P139Emacs Lispテクニックバイブル作者: るびきち出版社/メーカー: 技術評論社発売日: 2011/11/26メディア…

ウィンドウを選択する

;; 一時的にウィンドウを選択し、その後で元のウィンドウに戻す (save-selected-window (switch-to-buffer " test1") (insert "This is a test1") (select-window (split-window-vertically)) (switch-to-buffer " test2") (insert "This is a test2")) P131…

ウィンドウが分割されているかどうかを確かめる

(defun one-window-p-test () (interactive) ;; 分割されているときはnilを返す (message "nomini t:%s nil:%s" (one-window-p t) (one-window-p))) ;; C-x pでone-window-pの挙動を確認できる (global-set-key (kbd "C-x p") 'one-window-p-test) P129Emacs…