GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Adding-Generalized-Variables.html ・ emacs-doc.conao3.com

12.17.2 新しい setf フォームの定義

この節では、setf が操作可能な新しいフォームを定義する方法について説明します。

マクロ: gv-define-simple-setter name setter &optional fix-return

このマクロを使用すると、単純なケースにおいて setf メソッドを簡単に定義できます。name は関数、マクロ、または特殊形式の名前です。name を更新する直接対応する setter 関数(例:(gv-define-simple-setter car setcar))が存在する場合はいつでも、このマクロを使用できます。

このマクロは、次のような形式の呼び出しを変換します。

(setf (name args...) value)

~へ

(setter args... value)

このような setf の呼び出しは、value を返すとドキュメントに記載されています。例えば car や setcar の場合は問題ありません。setcar は自身が設定した値を返すためです。もし setter 関数が value を返さない場合は、gv-define-simple-setter の fix-return 引数に nil 以外の値を指定してください。これは、以下と同等の表現に展開されます。

(let ((temp value))
  (setter args... temp)
  temp)

ですので、正しい結果が返されるようにします。

マクロ: gv-define-setter name arglist &rest body

このマクロを使用すると、従来の形式よりも複雑な setf 展開が可能になります。例えば、呼び出すための単純なセッター関数がない場合や、関数はあるものの place 形式とは異なる引数を必要とする場合などに、この形式を利用する必要があるかもしれません。

このマクロは、まず setf 引数のフォーム (value args…) を arglist に従ってバインドし、次に body を実行することで、フォーム (setf (name args…) value) を展開します。body は代入を行う Lisp フォームを返し、最終的に設定された値を返す必要があります。このマクロの使用例は以下の通りです:

(gv-define-setter caar (val x) `(setcar (car ,x) ,val))
マクロ: gv-define-expander name handler

展開をより細かく制御するには、gv-define-expander マクロを使用できます。例えば、設定可能な substring は次のように実装できます。

(gv-define-expander substring
  (lambda (do place from &optional to)
    (gv-letplace (getter setter) place
      (macroexp-let2* (from to)
        (funcall do `(substring ,getter ,from ,to)
                 (lambda (v)
                   (macroexp-let2* (v)
                     `(progn
                        ,(funcall setter `(cl--set-substring
                                           ,getter ,from ,to ,v))
                        ,v))))))))
マクロ: gv-letplace (getter setter) place &rest body

マクロ gv-letplace は、setf と同様に動作するマクロを定義する際に有用です。例えば、Common Lisp の incf マクロは次のように実装できます:

(defmacro incf (place &optional n)
  (gv-letplace (getter setter) place
    (macroexp-let2* ((v (or n 1)))
      (funcall setter `(+ ,v ,getter)))))

getter には、place の値を返すコピー可能な式がバインドされます。setter には、式 v を受け取り、place を v に設定する新しい式を返す関数がバインドされます。body は、getter と setter を介して place を操作する Emacs Lisp 式を返す必要があります。

詳細はソースファイル gv.el を参照してください。

関数: make-obsolete-generalized-variable obsolete-name current-name when

この関数は、バイトコンパイラに対し、一般化変数 obsolete-name が廃止されたことを警告させます。current-name がシンボルの場合、警告メッセージには obsolete-name の代わりに current-name を使用するよう記載されます。current-name が文字列の場合、メッセージはこのようになります。when は、変数が最初に廃止された時期を示す文字列(通常はバージョン番号の文字列)である必要があります。

Common Lispに関する注記: Common Lispでは、関数のsetf動作を指定する別の方法として、名称がシンボルではなくリスト(setf name)であるsetf関数が定義されています。例えば、(defun (setf foo) …)はsetfがfooに適用される際に使用される関数を定義します。Emacsはこの機能をサポートしていません。適切な展開があらかじめ定義されていないフォームに対してsetfを使用すると、コンパイル時エラーとなります。Common Lispでは、関数(setf func)が後で定義される可能性があるため、これはエラーとはなりません。