by shigemk2

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

beforeアドバイス

アドバイスとは、関数を再定義することなく関数の挙動を変更する仕組みである。

たいていの場合はフックを使えば間に合うが、適切なフックがない場合は
関数を変更するしかない。

;; オリジナルの関数が呼び出される前に挙動を追加するにはbeforeアドバイスを使う。
(defun f1 () (princ "f1"))		; => f1
;; これが普通の挙動
(with-output-to-string (f1))		; => "before/f1"
;; 直前にbefore/を書き出すアドバイスを定義する
(defadvice f1 (before before-test activate)
  (princ "before/"))			; => f1
;; アドバイスで挙動が変わる
(with-output-to-string (f1))		; => "before/f1"
;; 関数を再定義しても反映される
(defun f1 () (princ "redefined"))
(with-output-to-string (f1))		; => "before/redefined"

(defun f2 (str) (princ str))
(defadvice f2 (before arg-test1 activate)
  (princ (upcase str)))
(with-output-to-string (f2 "x"))	; => "Xx"

(defadvice f2 (before arg-test1 activate)
  (princ (upcase (ad-get-arg 0))))	; => f2
(with-output-to-string (f2 "x"))	; => "Xx"

;; 関数の引数にアクセス
;; 元の関数の引数名にアクセスできるようになっている。
(defun f3 (&rest args))
(defadvice f3 (before arg-test2 activate)
  (ad-get-arg 0)			; => 1
  (ad-get-arg 1)			; => 2
  (ad-get-args 0)			; => (1 2 3 4)
  (ad-get-args 1)			; => (2 3 4)
  )
(f3 1 2 3 4)				; => nil

(defun f4 (x y) (+ x y))
(f4 3 5)				; => 9
(defadvice f4 (before ad-set-arg-test activate)
  (ad-set-arg 0 (1+ (ad-get-arg 0))))	; 引数に1を加える
(f4 3 5)				; => 9

(defun f5 (x y) (+ x y))
(f5 3 5)				; => 8
(defadvice f5 (before ad-set-args-test activate)
  (ad-set-args 0 '(10 20)))		; 引数を勝手にセット
(f5 3 5)				; => 30

P251

Emacs Lispテクニックバイブル

Emacs Lispテクニックバイブル