aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Kangas2025-02-22 17:32:31 +0100
committerStefan Kangas2025-02-23 00:38:22 +0100
commit95fee880e45184f4820e9704b75887ef2d91bd01 (patch)
tree09afd4a8d6f9ccf0f2cec36e4f604deaf040c728
parent44a1c4a9aea54d6542bcf0c231b080f0ed023229 (diff)
downloademacs-95fee880e45184f4820e9704b75887ef2d91bd01.tar.gz
emacs-95fee880e45184f4820e9704b75887ef2d91bd01.zip
New macros incf and decf
* lisp/emacs-lisp/cl-lib.el (cl-incf, cl-decf): Move macros from here... * lisp/emacs-lisp/gv.el (incf, decf): ...to here. Make old names into aliases, documented as deprecated. * lisp/obsolete/cl.el: Don't alias incf and decf. * test/lisp/emacs-lisp/cl-lib-tests.el (cl-lib-test-incf) (cl-lib-test-decf): Move tests from here... * test/lisp/emacs-lisp/gv-tests.el (gv-incf, gv-decf): ...to here. * doc/lispref/numbers.texi (Arithmetic Operations): * lisp/emacs-lisp/shortdoc.el (number): Document incf and decf. * doc/lispref/variables.texi (Multisession Variables): * doc/misc/cl.texi (Organization, Modify Macros, Modify Macros) (Modify Macros, Macro Bindings, For Clauses, Property Lists) (Structures, Efficiency Concerns, Obsolete Setf Customization): Delete cl-incf and cl-decf documentation, moving any relevant parts to lispref. Delete some parts that seem to primarily regard implementation details that do not warrant inclusion in lispref. Update all examples to use incf/decf.
-rw-r--r--doc/lispref/numbers.texi19
-rw-r--r--doc/lispref/variables.texi2
-rw-r--r--doc/misc/cl.texi112
-rw-r--r--etc/NEWS23
-rw-r--r--lisp/emacs-lisp/cl-lib.el22
-rw-r--r--lisp/emacs-lisp/gv.el32
-rw-r--r--lisp/emacs-lisp/shortdoc.el12
-rw-r--r--lisp/obsolete/cl.el2
-rw-r--r--test/lisp/emacs-lisp/cl-lib-tests.el36
-rw-r--r--test/lisp/emacs-lisp/gv-tests.el36
10 files changed, 135 insertions, 161 deletions
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index 17fa1e05fee..29105959ecd 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -668,8 +668,8 @@ foo
668 @result{} 4 668 @result{} 4
669@end example 669@end example
670 670
671If you want to increment the variable, you must use @code{setq}, 671If you want to increment the variable, you must use @code{setq} (or
672like this: 672@code{incf}), like this:
673 673
674@example 674@example
675(setq foo (1+ foo)) 675(setq foo (1+ foo))
@@ -681,6 +681,21 @@ like this:
681This function returns @var{number-or-marker} minus 1. 681This function returns @var{number-or-marker} minus 1.
682@end defun 682@end defun
683 683
684@defmac incf place &optional delta
685This macro increments the number stored in @var{place} by one, or
686by @var{delta} if specified. The incremented value is returned.
687
688@var{place} can be a symbol or a generalized variable, @xref{Generalized
689Variables}. For example, @code{(incf i)} is equivalent to
690@code{(setq i (1+ i))}, and @code{(incf (car x) 2)} is equivalent to
691@code{(setcar x (+ (car x) 2))}.
692@end defmac
693
694@defmac decf place &optional delta
695This macro decrements the number stored in @var{place} by one, or
696by @var{delta} if specified. The decremented value is returned.
697@end defmac
698
684@defun + &rest numbers-or-markers 699@defun + &rest numbers-or-markers
685This function adds its arguments together. When given no arguments, 700This function adds its arguments together. When given no arguments,
686@code{+} returns 0. 701@code{+} returns 0.
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 998a74d067a..46027edb041 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -3130,7 +3130,7 @@ If the multisession variable is synchronized, setting it may update
3130the value first. For instance: 3130the value first. For instance:
3131 3131
3132@lisp 3132@lisp
3133(cl-incf (multisession-value foo-bar)) 3133(incf (multisession-value foo-bar))
3134@end lisp 3134@end lisp
3135 3135
3136This first checks whether the value has changed in a different 3136This first checks whether the value has changed in a different
diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
index f95900a085e..8fb308e64a5 100644
--- a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ -168,9 +168,6 @@ and information about the package. This file is relatively compact.
168 168
169@item cl-extra.el 169@item cl-extra.el
170This file contains the larger, more complex or unusual functions. 170This file contains the larger, more complex or unusual functions.
171It is kept separate so that packages which only want to use Common
172Lisp fundamentals like the @code{cl-incf} function won't need to pay
173the overhead of loading the more advanced functions.
174 171
175@item cl-seq.el 172@item cl-seq.el
176This file contains most of the advanced functions for operating 173This file contains most of the advanced functions for operating
@@ -197,8 +194,8 @@ this package prior to Emacs 24.3. Nowadays, it is replaced by
197but use different function names (in fact, @file{cl.el} mainly just 194but use different function names (in fact, @file{cl.el} mainly just
198defines aliases to the @file{cl-lib.el} definitions). Where 195defines aliases to the @file{cl-lib.el} definitions). Where
199@file{cl-lib.el} defines a function called, for example, 196@file{cl-lib.el} defines a function called, for example,
200@code{cl-incf}, @file{cl.el} uses the same name but without the 197@code{cl-first}, @file{cl.el} uses the same name but without the
201@samp{cl-} prefix, e.g., @code{incf} in this example. There are a few 198@samp{cl-} prefix, e.g., @code{first} in this example. There are a few
202exceptions to this. First, functions such as @code{cl-defun} where 199exceptions to this. First, functions such as @code{cl-defun} where
203the unprefixed version was already used for a standard Emacs Lisp 200the unprefixed version was already used for a standard Emacs Lisp
204function. In such cases, the @file{cl.el} version adds a @samp{*} 201function. In such cases, the @file{cl.el} version adds a @samp{*}
@@ -1028,7 +1025,7 @@ generalized variables.
1028 1025
1029@menu 1026@menu
1030* Setf Extensions:: Additional @code{setf} places. 1027* Setf Extensions:: Additional @code{setf} places.
1031* Modify Macros:: @code{cl-incf}, @code{cl-rotatef}, @code{cl-letf}, @code{cl-callf}, etc. 1028* Modify Macros:: @code{cl-rotatef}, @code{cl-letf}, @code{cl-callf}, etc.
1032@end menu 1029@end menu
1033 1030
1034@node Setf Extensions 1031@node Setf Extensions
@@ -1085,52 +1082,6 @@ Specifically, all subforms are evaluated from left to right, then
1085all the assignments are done (in an undefined order). 1082all the assignments are done (in an undefined order).
1086@end defmac 1083@end defmac
1087 1084
1088@defmac cl-incf place &optional x
1089This macro increments the number stored in @var{place} by one, or
1090by @var{x} if specified. The incremented value is returned. For
1091example, @code{(cl-incf i)} is equivalent to @code{(setq i (1+ i))}, and
1092@code{(cl-incf (car x) 2)} is equivalent to @code{(setcar x (+ (car x) 2))}.
1093
1094As with @code{setf}, care is taken to preserve the ``apparent'' order
1095of evaluation. For example,
1096
1097@example
1098(cl-incf (aref vec (cl-incf i)))
1099@end example
1100
1101@noindent
1102appears to increment @code{i} once, then increment the element of
1103@code{vec} addressed by @code{i}; this is indeed exactly what it
1104does, which means the above form is @emph{not} equivalent to the
1105``obvious'' expansion,
1106
1107@example
1108(setf (aref vec (cl-incf i))
1109 (1+ (aref vec (cl-incf i)))) ; wrong!
1110@end example
1111
1112@noindent
1113but rather to something more like
1114
1115@example
1116(let ((temp (cl-incf i)))
1117 (setf (aref vec temp) (1+ (aref vec temp))))
1118@end example
1119
1120@noindent
1121Again, all of this is taken care of automatically by @code{cl-incf} and
1122the other generalized-variable macros.
1123
1124As a more Emacs-specific example of @code{cl-incf}, the expression
1125@code{(cl-incf (point) @var{n})} is essentially equivalent to
1126@code{(forward-char @var{n})}.
1127@end defmac
1128
1129@defmac cl-decf place &optional x
1130This macro decrements the number stored in @var{place} by one, or
1131by @var{x} if specified.
1132@end defmac
1133
1134@defmac cl-pushnew x place @t{&key :test :test-not :key} 1085@defmac cl-pushnew x place @t{&key :test :test-not :key}
1135This macro inserts @var{x} at the front of the list stored in 1086This macro inserts @var{x} at the front of the list stored in
1136@var{place}, but only if @var{x} isn't present in the list already. 1087@var{place}, but only if @var{x} isn't present in the list already.
@@ -1243,8 +1194,8 @@ It does the bindings in sequential rather than parallel order.
1243This is the ``generic'' modify macro. It calls @var{function}, 1194This is the ``generic'' modify macro. It calls @var{function},
1244which should be an unquoted function name, macro name, or lambda. 1195which should be an unquoted function name, macro name, or lambda.
1245It passes @var{place} and @var{args} as arguments, and assigns the 1196It passes @var{place} and @var{args} as arguments, and assigns the
1246result back to @var{place}. For example, @code{(cl-incf @var{place} 1197result back to @var{place}. For example, @code{(incf @var{place}
1247@var{n})} is the same as @code{(cl-callf + @var{place} @var{n})}. 1198@var{n})} could be implemented as @code{(cl-callf + @var{place} @var{n})}.
1248Some more examples: 1199Some more examples:
1249 1200
1250@example 1201@example
@@ -1264,7 +1215,7 @@ equivalent to @code{(cl-callf2 cons @var{x} @var{place})}.
1264@end defmac 1215@end defmac
1265 1216
1266The @code{cl-callf} and @code{cl-callf2} macros serve as building 1217The @code{cl-callf} and @code{cl-callf2} macros serve as building
1267blocks for other macros like @code{cl-incf}, and @code{cl-pushnew}. 1218blocks for other macros like @code{cl-pushnew}.
1268The @code{cl-letf} and @code{cl-letf*} macros are used in the processing 1219The @code{cl-letf} and @code{cl-letf*} macros are used in the processing
1269of symbol macros; @pxref{Macro Bindings}. 1220of symbol macros; @pxref{Macro Bindings}.
1270 1221
@@ -1401,7 +1352,7 @@ replaced by @var{expansion}.
1401@example 1352@example
1402(setq bar '(5 . 9)) 1353(setq bar '(5 . 9))
1403(cl-symbol-macrolet ((foo (car bar))) 1354(cl-symbol-macrolet ((foo (car bar)))
1404 (cl-incf foo)) 1355 (incf foo))
1405bar 1356bar
1406 @result{} (6 . 9) 1357 @result{} (6 . 9)
1407@end example 1358@end example
@@ -1426,7 +1377,7 @@ expansion of another macro:
1426 body)))) 1377 body))))
1427 1378
1428(setq mylist '(1 2 3 4)) 1379(setq mylist '(1 2 3 4))
1429(my-dolist (x mylist) (cl-incf x)) 1380(my-dolist (x mylist) (incf x))
1430mylist 1381mylist
1431 @result{} (2 3 4 5) 1382 @result{} (2 3 4 5)
1432@end example 1383@end example
@@ -1440,14 +1391,14 @@ shown here expands to
1440@example 1391@example
1441(cl-loop for G1234 on mylist do 1392(cl-loop for G1234 on mylist do
1442 (cl-symbol-macrolet ((x (car G1234))) 1393 (cl-symbol-macrolet ((x (car G1234)))
1443 (cl-incf x))) 1394 (incf x)))
1444@end example 1395@end example
1445 1396
1446@noindent 1397@noindent
1447which in turn expands to 1398which in turn expands to
1448 1399
1449@example 1400@example
1450(cl-loop for G1234 on mylist do (cl-incf (car G1234))) 1401(cl-loop for G1234 on mylist do (incf (car G1234)))
1451@end example 1402@end example
1452 1403
1453@xref{Loop Facility}, for a description of the @code{cl-loop} macro. 1404@xref{Loop Facility}, for a description of the @code{cl-loop} macro.
@@ -1999,7 +1950,7 @@ a @code{setf}-able ``reference'' onto the elements of the list
1999rather than just a temporary variable. For example, 1950rather than just a temporary variable. For example,
2000 1951
2001@example 1952@example
2002(cl-loop for x in-ref my-list do (cl-incf x)) 1953(cl-loop for x in-ref my-list do (incf x))
2003@end example 1954@end example
2004 1955
2005@noindent 1956@noindent
@@ -2940,7 +2891,7 @@ The @code{get} and @code{cl-get} functions are also @code{setf}-able.
2940The fact that @code{default} is ignored can sometimes be useful: 2891The fact that @code{default} is ignored can sometimes be useful:
2941 2892
2942@example 2893@example
2943(cl-incf (cl-get 'foo 'usage-count 0)) 2894(incf (cl-get 'foo 'usage-count 0))
2944@end example 2895@end example
2945 2896
2946Here, symbol @code{foo}'s @code{usage-count} property is incremented 2897Here, symbol @code{foo}'s @code{usage-count} property is incremented
@@ -4051,7 +4002,7 @@ calling @code{(person-first-name @var{p})}, @code{(person-age
4051slots by using @code{setf} on any of these place forms, for example: 4002slots by using @code{setf} on any of these place forms, for example:
4052 4003
4053@example 4004@example
4054(cl-incf (person-age birthday-boy)) 4005(incf (person-age birthday-boy))
4055@end example 4006@end example
4056 4007
4057You can create a new @code{person} by calling @code{make-person}, 4008You can create a new @code{person} by calling @code{make-person},
@@ -4459,29 +4410,14 @@ user to modify @var{place}.
4459Many of the advanced features of this package, such as @code{cl-defun}, 4410Many of the advanced features of this package, such as @code{cl-defun},
4460@code{cl-loop}, etc., are implemented as Lisp macros. In 4411@code{cl-loop}, etc., are implemented as Lisp macros. In
4461byte-compiled code, these complex notations will be expanded into 4412byte-compiled code, these complex notations will be expanded into
4462equivalent Lisp code which is simple and efficient. For example, 4413equivalent Lisp code which is simple and efficient. Thus, there is no
4463the form 4414performance penalty for using the more readable form in your compiled
4464 4415code.
4465@example
4466(cl-incf i n)
4467@end example
4468
4469@noindent
4470is expanded at compile-time to the Lisp form
4471
4472@example
4473(setq i (+ i n))
4474@end example
4475
4476@noindent
4477which is the most efficient way of doing this operation
4478in Lisp. Thus, there is no performance penalty for using the more
4479readable @code{cl-incf} form in your compiled code.
4480 4416
4481@emph{Interpreted} code, on the other hand, must expand these macros 4417@emph{Interpreted} code, on the other hand, must expand these macros
4482every time they are executed. For this reason it is strongly 4418every time they are executed. For this reason it is strongly
4483recommended that code making heavy use of macros be compiled. 4419recommended that code making heavy use of macros be compiled.
4484A loop using @code{cl-incf} a hundred times will execute considerably 4420A loop using @code{cl-first} a hundred times will execute considerably
4485faster if compiled, and will also garbage-collect less because the 4421faster if compiled, and will also garbage-collect less because the
4486macro expansion will not have to be generated, used, and thrown away a 4422macro expansion will not have to be generated, used, and thrown away a
4487hundred times. 4423hundred times.
@@ -4907,7 +4843,7 @@ call to @code{make-adder} itself.
4907@example 4843@example
4908(defun make-counter () 4844(defun make-counter ()
4909 (lexical-let ((n 0)) 4845 (lexical-let ((n 0))
4910 (cl-function (lambda (&optional (m 1)) (cl-incf n m))))) 4846 (cl-function (lambda (&optional (m 1)) (incf n m)))))
4911(setq count-1 (make-counter)) 4847(setq count-1 (make-counter))
4912(funcall count-1 3) 4848(funcall count-1 3)
4913 @result{} 3 4849 @result{} 3
@@ -5052,7 +4988,7 @@ In Emacs, these are obsolete, replaced by various features of
5052 4988
5053@defmac define-modify-macro name arglist function [doc-string] 4989@defmac define-modify-macro name arglist function [doc-string]
5054This macro defines a ``read-modify-write'' macro similar to 4990This macro defines a ``read-modify-write'' macro similar to
5055@code{cl-incf} and @code{cl-decf}. You can replace this macro 4991@code{incf} and @code{decf}. You can replace this macro
5056with @code{gv-letplace}. 4992with @code{gv-letplace}.
5057 4993
5058The macro @var{name} is defined to take a @var{place} argument 4994The macro @var{name} is defined to take a @var{place} argument
@@ -5180,8 +5116,8 @@ For example, the simple form of @code{defsetf} is shorthand for
5180 5116
5181The Lisp form that is returned can access the arguments from 5117The Lisp form that is returned can access the arguments from
5182@var{arglist} and @var{store-var} in an unrestricted fashion; 5118@var{arglist} and @var{store-var} in an unrestricted fashion;
5183macros like @code{cl-incf} that invoke this 5119macros that invoke this
5184setf-method will insert temporary variables as needed to make 5120setf-method should insert temporary variables as needed to make
5185sure the apparent order of evaluation is preserved. 5121sure the apparent order of evaluation is preserved.
5186 5122
5187Another standard example: 5123Another standard example:
@@ -5245,11 +5181,7 @@ temporary variables. In the setf-methods generated by
5245@code{defsetf}, the second return value is simply the list of 5181@code{defsetf}, the second return value is simply the list of
5246arguments in the place form, and the first return value is a 5182arguments in the place form, and the first return value is a
5247list of a corresponding number of temporary variables generated 5183list of a corresponding number of temporary variables generated
5248@c FIXME I don't think this is true anymore. 5184by @code{cl-gensym}.
5249by @code{cl-gensym}. Macros like @code{cl-incf} that
5250use this setf-method will optimize away most temporaries that
5251turn out to be unnecessary, so there is little reason for the
5252setf-method itself to optimize.
5253@end defmac 5185@end defmac
5254 5186
5255@node GNU Free Documentation License 5187@node GNU Free Documentation License
diff --git a/etc/NEWS b/etc/NEWS
index a03ffe91ab9..0c54fc2c4a9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -491,12 +491,18 @@ Emacs 25.1), and gnudoit (obsolete since Emacs 25.1).
491** CL-Lib 491** CL-Lib
492 492
493+++ 493+++
494*** Some cl-lib functions are now built-in. 494*** Some cl-lib functions and macros are now built-in.
495The functions 'cl-plusp', 'cl-minusp', 'cl-oddp', and 'cl-evenp', have 495These functions or macros have been added to Emacs Lisp, and the old
496been added to Emacs Lisp, and are thus now aliases for the built-in 496names are now aliases for the built-in equivalents:
497functions 'plusp', 'minusp', 'oddp' and 'evenp'. The old names are 497 - 'cl-incf' renamed to 'incf'
498considered deprecated, and will be marked as obsolete in some future 498 - 'cl-decf' renamed to 'decf'
499release. 499 - 'cl-oddp' renamed to 'oddp'
500 - 'cl-evenp' renamed to 'evenp'
501 - 'cl-plusp' renamed to 'plusp'
502 - 'cl-minusp' renamed to 'minusp'
503
504The old names are considered deprecated, and will be marked as obsolete
505in some future release.
500 506
501+++ 507+++
502*** 'cl-labels' now also accepts '(FUNC EXP)' bindings, like 'cl-flet'. 508*** 'cl-labels' now also accepts '(FUNC EXP)' bindings, like 'cl-flet'.
@@ -1357,6 +1363,11 @@ change it globally with:
1357 (set-default-toplevel-value 'lexical-binding t) 1363 (set-default-toplevel-value 'lexical-binding t)
1358 1364
1359+++ 1365+++
1366*** New functions 'incf' and 'decf'.
1367They increment or decrement the value stored in a variable (a symbol),
1368or in a generalized variable.
1369
1370+++
1360** New functions 'plusp' and 'minusp'. 1371** New functions 'plusp' and 'minusp'.
1361They return non-nil if a number is positive or negative, respectively, 1372They return non-nil if a number is positive or negative, respectively,
1362and signal an error if they are given a non-number. 1373and signal an error if they are given a non-number.
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index 2a952b57646..42460fc2c9f 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -105,29 +105,27 @@ a future Emacs interpreter will be able to use it.")
105;; can safely be used in init files. 105;; can safely be used in init files.
106 106
107;;;###autoload 107;;;###autoload
108(defmacro cl-incf (place &optional x) 108(defalias 'cl-incf #'incf
109 "Increment PLACE by X (1 by default). 109 "Increment PLACE by X (1 by default).
110PLACE may be a symbol, or any generalized variable allowed by `setf'. 110PLACE may be a symbol, or any generalized variable allowed by `setf'.
111The return value is the incremented value of PLACE. 111The return value is the incremented value of PLACE.
112 112
113If X is specified, it should be an expression that should 113If X is specified, it should be an expression that should
114evaluate to a number." 114evaluate to a number.
115 (declare (debug (place &optional form))) 115
116 (if (symbolp place) 116This macro is considered deprecated in favor of the built-in macro
117 (list 'setq place (if x (list '+ place x) (list '1+ place))) 117`incf' that was added in Emacs 31.1.")
118 (list 'cl-callf '+ place (or x 1))))
119 118
120(defmacro cl-decf (place &optional x) 119(defalias 'cl-decf #'decf
121 "Decrement PLACE by X (1 by default). 120 "Decrement PLACE by X (1 by default).
122PLACE may be a symbol, or any generalized variable allowed by `setf'. 121PLACE may be a symbol, or any generalized variable allowed by `setf'.
123The return value is the decremented value of PLACE. 122The return value is the decremented value of PLACE.
124 123
125If X is specified, it should be an expression that should 124If X is specified, it should be an expression that should
126evaluate to a number." 125evaluate to a number.
127 (declare (debug cl-incf)) 126
128 (if (symbolp place) 127This macro is considered deprecated in favor of the built-in macro
129 (list 'setq place (if x (list '- place x) (list '1- place))) 128`decf' that was added in Emacs 31.1.")
130 (list 'cl-callf '- place (or x 1))))
131 129
132(defmacro cl-pushnew (x place &rest keys) 130(defmacro cl-pushnew (x place &rest keys)
133 "Add X to the list stored in PLACE unless X is already in the list. 131 "Add X to the list stored in PLACE unless X is already in the list.
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index dcbdf6942f7..d9ba786aa7d 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -315,17 +315,29 @@ The return value is the last VAL in the list.
315;; `(if (member ,v ,getter) nil 315;; `(if (member ,v ,getter) nil
316;; ,(funcall setter `(cons ,v ,getter)))))) 316;; ,(funcall setter `(cons ,v ,getter))))))
317 317
318;; (defmacro gv-inc! (place &optional val) 318;;;###autoload
319;; "Increment PLACE by VAL (default to 1)." 319(defmacro incf (place &optional delta)
320;; (declare (debug (gv-place &optional form))) 320 "Increment PLACE by DELTA (default to 1).
321;; (gv-letplace (getter setter) place
322;; (funcall setter `(+ ,getter ,(or val 1)))))
323 321
324;; (defmacro gv-dec! (place &optional val) 322The DELTA is first added to PLACE, and then stored in PLACE.
325;; "Decrement PLACE by VAL (default to 1)." 323Return the incremented value of PLACE.
326;; (declare (debug (gv-place &optional form))) 324
327;; (gv-letplace (getter setter) place 325See also `decf'."
328;; (funcall setter `(- ,getter ,(or val 1))))) 326 (declare (debug (gv-place &optional form)))
327 (gv-letplace (getter setter) place
328 (funcall setter `(+ ,getter ,(or delta 1)))))
329
330;;;###autoload
331(defmacro decf (place &optional delta)
332 "Decrement PLACE by DELTA (default to 1).
333
334The DELTA is first subtracted from PLACE, and then stored in PLACE.
335Return the decremented value of PLACE.
336
337See also `incf'."
338 (declare (debug (gv-place &optional form)))
339 (gv-letplace (getter setter) place
340 (funcall setter `(- ,getter ,(or delta 1)))))
329 341
330;; For Edebug, the idea is to let Edebug instrument gv-places just like it does 342;; For Edebug, the idea is to let Edebug instrument gv-places just like it does
331;; for normal expressions, and then give it a gv-expander to DTRT. 343;; for normal expressions, and then give it a gv-expander to DTRT.
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 23b9b582a9a..77a4ec4f21c 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1375,9 +1375,17 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
1375 :eval (mod 10 6) 1375 :eval (mod 10 6)
1376 :eval (mod 10.5 6)) 1376 :eval (mod 10.5 6))
1377 (1+ 1377 (1+
1378 :eval (1+ 2)) 1378 :eval (1+ 2)
1379 :eval (let ((x 2)) (1+ x) x))
1379 (1- 1380 (1-
1380 :eval (1- 4)) 1381 :eval (1- 4)
1382 :eval (let ((x 4)) (1- x) x))
1383 (incf
1384 :eval (let ((x 2)) (incf x) x)
1385 :eval (let ((x 2)) (incf x 2) x))
1386 (decf
1387 :eval (let ((x 4)) (decf x) x)
1388 :eval (let ((x 4)) (decf x 2)) x)
1381 "Predicates" 1389 "Predicates"
1382 (= 1390 (=
1383 :args (number &rest numbers) 1391 :args (number &rest numbers)
diff --git a/lisp/obsolete/cl.el b/lisp/obsolete/cl.el
index 5baa155c592..5fbfbb7899e 100644
--- a/lisp/obsolete/cl.el
+++ b/lisp/obsolete/cl.el
@@ -282,8 +282,6 @@
282 values-list 282 values-list
283 values 283 values
284 pushnew 284 pushnew
285 decf
286 incf
287 )) 285 ))
288 (let ((new (if (consp fun) (prog1 (cdr fun) (setq fun (car fun))) 286 (let ((new (if (consp fun) (prog1 (cdr fun) (setq fun (car fun)))
289 (intern (format "cl-%s" fun))))) 287 (intern (format "cl-%s" fun)))))
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el
index 376566958a0..d7c38b73432 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -63,42 +63,6 @@
63 (should (equal (cl-multiple-value-list nil) nil)) 63 (should (equal (cl-multiple-value-list nil) nil))
64 (should (equal (cl-multiple-value-list (list 1 2 3)) '(1 2 3)))) 64 (should (equal (cl-multiple-value-list (list 1 2 3)) '(1 2 3))))
65 65
66(defvar cl-lib-test--special 0)
67
68(ert-deftest cl-lib-test-incf ()
69 (setq cl-lib-test--special 0)
70 (should (= (cl-incf cl-lib-test--special) 1))
71 (should (= cl-lib-test--special 1))
72 (should (= (cl-incf cl-lib-test--special 9) 10))
73 (should (= cl-lib-test--special 10))
74 (let ((var 0))
75 (should (= (cl-incf var) 1))
76 (should (= var 1))
77 (should (= (cl-incf var 9) 10))
78 (should (= var 10)))
79 (let ((alist))
80 (should (= (cl-incf (alist-get 'a alist 0)) 1))
81 (should (= (alist-get 'a alist 0) 1))
82 (should (= (cl-incf (alist-get 'a alist 0) 9) 10))
83 (should (= (alist-get 'a alist 0) 10))))
84
85(ert-deftest cl-lib-test-decf ()
86 (setq cl-lib-test--special 0)
87 (should (= (cl-decf cl-lib-test--special) -1))
88 (should (= cl-lib-test--special -1))
89 (should (= (cl-decf cl-lib-test--special 9) -10))
90 (should (= cl-lib-test--special -10))
91 (let ((var 1))
92 (should (= (cl-decf var) 0))
93 (should (= var 0))
94 (should (= (cl-decf var 10) -10))
95 (should (= var -10)))
96 (let ((alist))
97 (should (= (cl-decf (alist-get 'a alist 0)) -1))
98 (should (= (alist-get 'a alist 0) -1))
99 (should (= (cl-decf (alist-get 'a alist 0) 9) -10))
100 (should (= (alist-get 'a alist 0) -10))))
101
102(ert-deftest cl-digit-char-p () 66(ert-deftest cl-digit-char-p ()
103 (should (eql 3 (cl-digit-char-p ?3))) 67 (should (eql 3 (cl-digit-char-p ?3)))
104 (should (eql 10 (cl-digit-char-p ?a 11))) 68 (should (eql 10 (cl-digit-char-p ?a 11)))
diff --git a/test/lisp/emacs-lisp/gv-tests.el b/test/lisp/emacs-lisp/gv-tests.el
index 5ea386e0b5d..892af4bfab1 100644
--- a/test/lisp/emacs-lisp/gv-tests.el
+++ b/test/lisp/emacs-lisp/gv-tests.el
@@ -163,6 +163,42 @@ its getter (Bug#41853)."
163 (eval-buffer)))) 163 (eval-buffer))))
164 (should (equal (get 'gv-setter-edebug 'gv-setter-edebug-prop) '(123)))) 164 (should (equal (get 'gv-setter-edebug 'gv-setter-edebug-prop) '(123))))
165 165
166(defvar gv-test--special 0)
167
168(ert-deftest gv-incf ()
169 (setq gv-test--special 0)
170 (should (= (incf gv-test--special) 1))
171 (should (= gv-test--special 1))
172 (should (= (incf gv-test--special 9) 10))
173 (should (= gv-test--special 10))
174 (let ((var 0))
175 (should (= (incf var) 1))
176 (should (= var 1))
177 (should (= (incf var 9) 10))
178 (should (= var 10)))
179 (let ((alist))
180 (should (= (incf (alist-get 'a alist 0)) 1))
181 (should (= (alist-get 'a alist 0) 1))
182 (should (= (incf (alist-get 'a alist 0) 9) 10))
183 (should (= (alist-get 'a alist 0) 10))))
184
185(ert-deftest gv-decf ()
186 (setq gv-test--special 0)
187 (should (= (decf gv-test--special) -1))
188 (should (= gv-test--special -1))
189 (should (= (decf gv-test--special 9) -10))
190 (should (= gv-test--special -10))
191 (let ((var 1))
192 (should (= (decf var) 0))
193 (should (= var 0))
194 (should (= (decf var 10) -10))
195 (should (= var -10)))
196 (let ((alist))
197 (should (= (decf (alist-get 'a alist 0)) -1))
198 (should (= (alist-get 'a alist 0) -1))
199 (should (= (decf (alist-get 'a alist 0) 9) -10))
200 (should (= (alist-get 'a alist 0) -10))))
201
166(ert-deftest gv-plist-get () 202(ert-deftest gv-plist-get ()
167 ;; Simple `setf' usage for `plist-get'. 203 ;; Simple `setf' usage for `plist-get'.
168 (let ((target (list :a "a" :b "b" :c "c"))) 204 (let ((target (list :a "a" :b "b" :c "c")))