1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
<h4 class="subsection">Defining new setf forms</h4> <p>This section describes how to define new forms that <code>setf</code> can operate on. </p> <dl> <dt id="gv-define-simple-setter">Macro: <strong>gv-define-simple-setter</strong> <em>name setter &optional fix-return</em>
</dt> <dd>
<p>This macro enables you to easily define <code>setf</code> methods for simple cases. <var>name</var> is the name of a function, macro, or special form. You can use this macro whenever <var>name</var> has a directly corresponding <var>setter</var> function that updates it, e.g., <code>(gv-define-simple-setter car setcar)</code>. </p> <p>This macro translates a call of the form </p> <div class="example"> <pre class="example">(setf (<var>name</var> <var>args</var>…) <var>value</var>)
</pre>
</div> <p>into </p>
<div class="example"> <pre class="example">(<var>setter</var> <var>args</var>… <var>value</var>)
</pre>
</div> <p>Such a <code>setf</code> call is documented to return <var>value</var>. This is no problem with, e.g., <code>car</code> and <code>setcar</code>, because <code>setcar</code> returns the value that it set. If your <var>setter</var> function does not return <var>value</var>, use a non-<code>nil</code> value for the <var>fix-return</var> argument of <code>gv-define-simple-setter</code>. This expands into something equivalent to </p>
<div class="example"> <pre class="example">(let ((temp <var>value</var>))
(<var>setter</var> <var>args</var>… temp)
temp)
</pre>
</div> <p>so ensuring that it returns the correct result. </p>
</dd>
</dl> <dl> <dt id="gv-define-setter">Macro: <strong>gv-define-setter</strong> <em>name arglist &rest body</em>
</dt> <dd>
<p>This macro allows for more complex <code>setf</code> expansions than the previous form. You may need to use this form, for example, if there is no simple setter function to call, or if there is one but it requires different arguments to the place form. </p> <p>This macro expands the form <code>(setf (<var>name</var> <var>args</var>…) <var>value</var>)</code> by first binding the <code>setf</code> argument forms <code>(<var>value</var> <var>args</var>…)</code> according to <var>arglist</var>, and then executing <var>body</var>. <var>body</var> should return a Lisp form that does the assignment, and finally returns the value that was set. An example of using this macro is: </p> <div class="example"> <pre class="example">(gv-define-setter caar (val x) `(setcar (car ,x) ,val))
</pre>
</div> </dd>
</dl> <dl> <dt id="gv-define-expander">Macro: <strong>gv-define-expander</strong> <em>name handler</em>
</dt> <dd>
<p>For more control over the expansion, the <code>gv-define-expander</code> macro can be used. For instance, a settable <code>substring</code> could be implemented this way: </p> <div class="example"> <pre class="example">(gv-define-expander substring
(lambda (do place from &optional to)
(gv-letplace (getter setter) place
(macroexp-let2* nil ((start from) (end to))
(funcall do `(substring ,getter ,start ,end)
(lambda (v)
(macroexp-let2 nil v v
`(progn
,(funcall setter `(cl--set-substring
,getter ,start ,end ,v))
,v))))))))
</pre>
</div> </dd>
</dl> <dl> <dt id="gv-letplace">Macro: <strong>gv-letplace</strong> <em>(getter setter) place &rest body</em>
</dt> <dd>
<p>The macro <code>gv-letplace</code> can be useful in defining macros that perform similarly to <code>setf</code>; for example, the <code>incf</code> macro of Common Lisp could be implemented this way: </p> <div class="example"> <pre class="example">(defmacro incf (place &optional n)
(gv-letplace (getter setter) place
(macroexp-let2 nil v (or n 1)
(funcall setter `(+ ,v ,getter)))))
</pre>
</div> <p><var>getter</var> will be bound to a copyable expression that returns the value of <var>place</var>. <var>setter</var> will be bound to a function that takes an expression <var>v</var> and returns a new expression that sets <var>place</var> to <var>v</var>. <var>body</var> should return a Emacs Lisp expression manipulating <var>place</var> via <var>getter</var> and <var>setter</var>. </p>
</dd>
</dl> <p>Consult the source file <samp>gv.el</samp> for more details. </p> <blockquote> <p><b>Common Lisp note:</b> Common Lisp defines another way to specify the <code>setf</code> behavior of a function, namely <code>setf</code> functions, whose names are lists <code>(setf <var>name</var>)</code> rather than symbols. For example, <code>(defun (setf foo) …)</code> defines the function that is used when <code>setf</code> is applied to <code>foo</code>. Emacs does not support this. It is a compile-time error to use <code>setf</code> on a form that has not already had an appropriate expansion defined. In Common Lisp, this is not an error since the function <code>(setf
<var>func</var>)</code> might be defined later. </p>
</blockquote><div class="_attribution">
<p class="_attribution-p">
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
<a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Adding-Generalized-Variables.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Adding-Generalized-Variables.html</a>
</p>
</div>
|