From: "Basil L. Contovounesios" <contovob@tcd.ie>
To: Oleh Krehel <oleh@oremacs.com>
Cc: emacs-devel@gnu.org
Subject: Re: 7 logical-xor implementations in source tree
Date: Wed, 24 Jul 2019 23:17:51 +0100 [thread overview]
Message-ID: <87sgqvoz5c.fsf@tcd.ie> (raw)
In-Reply-To: <87pnm14u95.fsf@tcd.ie> (Basil L. Contovounesios's message of "Mon, 22 Jul 2019 22:47:02 +0100")
[-- Attachment #1: 0001-Add-conditional-operators-xor-and-equiv-to-subr.el.patch --]
[-- Type: text/x-diff, Size: 21713 bytes --]
From 78a4b6153315b6c83af5d802a71eb15734c0a07f Mon Sep 17 00:00:00 2001
From: "Basil L. Contovounesios" <contovob@tcd.ie>
Date: Tue, 9 Apr 2019 02:23:41 +0100
Subject: [PATCH] Add conditional operators xor and equiv to subr.el
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Suggested by Oleh Krehel <oleh@oremacs.com> and provided by Mattias
Engdegård <mattiase@acm.org> in the following thread:
https://lists.gnu.org/archive/html/emacs-devel/2019-07/msg00547.html
* lisp/array.el (xor): Move unused function from here...
* lisp/subr.el: ...to here.
(equiv): New macro.
* lisp/gnus/spam.el (spam-xor):
* lisp/play/5x5.el (5x5-xor):
* lisp/proced.el (proced-xor):
* lisp/progmodes/idlwave.el (idlwave-xor):
* lisp/vc/diff-mode.el (diff-xor): Define as obsolete aliases of,
and replace all uses with, xor.
* lisp/jsonrpc.el: Remove unused dependency on array.el.
* lisp/org/org.el (org-xor): Move from here...
* lisp/org/org-compat.el (org-xor): ...to here, as a compatibility
shim for xor.
* lisp/progmodes/idlw-shell.el (idlwave-shell-enable-all-bp):
* lisp/simple.el (exchange-point-and-mark): Use equiv.
* lisp/strokes.el (strokes-xor): Remove commented-out xor
implementation.
* lisp/windmove.el (windmove-display-in-direction): Use xor.
* doc/lispref/control.texi (Control Structures): Extend menu entry
for new combining conditions.
(Combining Conditions):
* etc/NEWS (Lisp Changes): Document xor and equiv.
* test/lisp/subr-tests.el (subr-test-xor, subr-test-equiv): New
tests.
---
doc/lispref/control.texi | 64 ++++++++++++++++++++++++++++++++++--
etc/NEWS | 12 +++++++
lisp/array.el | 5 ---
lisp/gnus/spam.el | 6 ++--
lisp/jsonrpc.el | 1 -
lisp/org/org-compat.el | 8 +++++
lisp/org/org.el | 4 ---
lisp/play/5x5.el | 8 ++---
lisp/proced.el | 11 +++----
lisp/progmodes/idlw-shell.el | 2 +-
lisp/progmodes/idlwave.el | 25 +++++++-------
lisp/simple.el | 3 +-
lisp/strokes.el | 6 ----
lisp/subr.el | 20 +++++++++++
lisp/vc/diff-mode.el | 12 +++----
lisp/windmove.el | 2 +-
test/lisp/subr-tests.el | 22 +++++++++++++
17 files changed, 153 insertions(+), 58 deletions(-)
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index de6cd9301f..49ad44932b 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -38,7 +38,7 @@ Control Structures
@menu
* Sequencing:: Evaluation in textual order.
* Conditionals:: @code{if}, @code{cond}, @code{when}, @code{unless}.
-* Combining Conditions:: @code{and}, @code{or}, @code{not}.
+* Combining Conditions:: @code{and}, @code{or}, @code{not}, and friends.
* Pattern-Matching Conditional:: How to use @code{pcase} and friends.
* Iteration:: @code{while} loops.
* Generators:: Generic sequences and coroutines.
@@ -298,8 +298,8 @@ Combining Conditions
@section Constructs for Combining Conditions
@cindex combining conditions
- This section describes three constructs that are often used together
-with @code{if} and @code{cond} to express complicated conditions. The
+ This section describes constructs that are often used together with
+@code{if} and @code{cond} to express complicated conditions. The
constructs @code{and} and @code{or} can also be used individually as
kinds of multiple conditional constructs.
@@ -419,6 +419,64 @@ Combining Conditions
@var{arg3})} never evaluates any argument more than once.
@end defspec
+@defmac equiv &rest conditions
+The @code{equiv} macro tests whether all the @var{conditions} are
+logically equivalent, i.e., either all @code{nil} or all
+non-@code{nil}. It works by evaluating the @var{conditions} one by
+one in the order written.
+
+If any of the @var{conditions} evaluates to a value logically
+different from its preceding @var{conditions}, then the result of the
+@code{equiv} must be @code{nil} regardless of the remaining
+@var{conditions}; so @code{equiv} returns @code{nil} right away,
+ignoring the remaining @var{conditions}.
+
+If all the @var{conditions} turn out non-@code{nil}, then the
+@code{equiv} expression returns the value of the last one. Otherwise,
+if all the @var{conditions} turn out @code{nil}, @code{equiv} returns
+@code{t}. Just @code{(equiv)}, with no @var{conditions}, also returns
+@code{t}, appropriate because all the @var{conditions} turned out
+logically equivalent. (Think about it; which one did not?)
+
+For example, the following expression tests whether either some state
+is enabled (@var{enabled} is non-@code{nil}) and should be disabled
+(@var{disable} is also non-@code{nil}), or the state is disabled
+(@var{enabled} is @code{nil}) and should be enabled (@var{disable} is
+also @code{nil}); if either of these conditions holds, the state
+should subsequently be toggled:
+
+@example
+(when (equiv enabled disable)
+ ;; Toggle state
+ @dots{})
+@end example
+
+Like the @code{and} construct, @code{equiv} can be written in terms of
+@code{if} or @code{cond}, though not quite as naturally. Here's how:
+
+@example
+@group
+(equiv @var{arg1} @var{arg2} @var{arg3})
+@equiv{}
+(if @var{arg1} (if @var{arg2} @var{arg3})
+ (if @var{arg2} nil
+ (if @var{arg3} nil t)))
+@equiv{}
+(cond (@var{arg1} (cond (@var{arg2} @var{arg3})))
+ (@var{arg2} nil)
+ (@var{arg3} nil)
+ (t))
+@end group
+@end example
+@end defmac
+
+@defun xor condition1 condition2
+This function returns the boolean exclusive-or of @var{condition1} and
+@var{condition2}. That is, @code{xor} returns @code{nil} if either
+both arguments are @code{nil}, or both are non-@code{nil}. Otherwise,
+it returns the value of that argument which is non-@code{nil}.
+@end defun
+
@node Pattern-Matching Conditional
@section Pattern-Matching Conditional
@cindex pcase
diff --git a/etc/NEWS b/etc/NEWS
index 5313270411..25e5fe9574 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2390,6 +2390,18 @@ the Emacs Lisp manual.
** `directory-files-recursively' can now take an optional PREDICATE
parameter to control descending into subdirectories.
++++
+** New function 'xor' returns the boolean exclusive-or if its args.
+The function was previously defined in array.el, but has been moved to
+subr.el so that it is available by default. Several duplicates of
+'xor' in other packages are now obsolete aliases of 'xor'.
+
++++
+** New macro 'equiv' tests whether its args are logically equivalent.
+If its arguments are all non-nil, 'equiv' returns the value of the
+last one; if they are all nil, it returns t; otherwise, its evaluation
+short-circuits and returns nil.
+
\f
* Changes in Emacs 27.1 on Non-Free Operating Systems
diff --git a/lisp/array.el b/lisp/array.el
index 2fffe0197e..965e97ff55 100644
--- a/lisp/array.el
+++ b/lisp/array.el
@@ -740,11 +740,6 @@ limit-index
((> index limit) limit)
(t index)))
-(defun xor (pred1 pred2)
- "Return the logical exclusive or of predicates PRED1 and PRED2."
- (and (or pred1 pred2)
- (not (and pred1 pred2))))
-
(defun current-line ()
"Return the current buffer line at point. The first line is 0."
(count-lines (point-min) (line-beginning-position)))
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index d752bf0efe..f990e0cba1 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -708,9 +708,7 @@ spam-clear-cache
"Clear the `spam-caches' entry for a check."
(remhash symbol spam-caches))
-(defun spam-xor (a b)
- "Logical A xor B."
- (and (or a b) (not (and a b))))
+(define-obsolete-function-alias 'spam-xor 'xor "27.1")
(defun spam-set-difference (list1 list2)
"Return a set difference of LIST1 and LIST2.
@@ -2550,7 +2548,7 @@ spam-spamoracle-learn
(goto-char (point-min))
(dolist (article articles)
(insert (spam-get-article-as-string article)))
- (let* ((arg (if (spam-xor unregister article-is-spam-p)
+ (let* ((arg (if (xor unregister article-is-spam-p)
"-spam"
"-good"))
(status
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index 0fffee6866..85fd40ecd2 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -43,7 +43,6 @@
(require 'warnings)
(require 'pcase)
(require 'ert) ; to escape a `condition-case-unless-debug'
-(require 'array) ; xor
\f
;;; Public API
diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el
index 062bb4c5ca..bb927fedf9 100644
--- a/lisp/org/org-compat.el
+++ b/lisp/org/org-compat.el
@@ -362,6 +362,14 @@ 'org-texinfo-def-table-markup
\f
;;; Miscellaneous functions
+;; `xor' was added in Emacs 27.1.
+(defalias 'org-xor
+ (if (fboundp 'xor)
+ #'xor
+ (lambda (a b)
+ "Exclusive or."
+ (if a (not b) b))))
+
(defun org-version-check (version feature level)
(let* ((v1 (mapcar 'string-to-number (split-string version "[.]")))
(v2 (mapcar 'string-to-number (split-string emacs-version "[.]")))
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 5aa49b29d6..79725ac752 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -10068,10 +10068,6 @@ org-link-unescape-single-byte-sequence
(char-to-string (string-to-number byte 16)))
(cdr (split-string hex "%")) ""))
-(defun org-xor (a b)
- "Exclusive or."
- (if a (not b) b))
-
(defun org-fixup-message-id-for-http (s)
"Replace special characters in a message id, so it can be used in an http query."
(when (string-match "%" s)
diff --git a/lisp/play/5x5.el b/lisp/play/5x5.el
index 28748cc351..c5d4659123 100644
--- a/lisp/play/5x5.el
+++ b/lisp/play/5x5.el
@@ -435,8 +435,8 @@ 5x5-make-xor-with-mutation
(dotimes (y 5x5-grid-size)
(dotimes (x 5x5-grid-size)
(5x5-set-cell xored y x
- (5x5-xor (5x5-cell current y x)
- (5x5-cell best y x)))))
+ (xor (5x5-cell current y x)
+ (5x5-cell best y x)))))
(5x5-mutate-solution xored)))
(defun 5x5-mutate-solution (solution)
@@ -931,9 +931,7 @@ 5x5-randomize
;; Support functions
-(defun 5x5-xor (x y)
- "Boolean exclusive-or of X and Y."
- (and (or x y) (not (and x y))))
+(define-obsolete-function-alias '5x5-xor 'xor "27.1")
(defun 5x5-y-or-n-p (prompt)
"5x5 wrapper for `y-or-n-p' which respects the `5x5-hassle-me' setting."
diff --git a/lisp/proced.el b/lisp/proced.el
index b05046bfbd..f8685d3c2f 100644
--- a/lisp/proced.el
+++ b/lisp/proced.el
@@ -1194,10 +1194,7 @@ proced-time-lessp
;;; Sorting
-(defsubst proced-xor (b1 b2)
- "Return the logical exclusive or of args B1 and B2."
- (and (or b1 b2)
- (not (and b1 b2))))
+(define-obsolete-function-alias 'proced-xor 'xor "27.1")
(defun proced-sort-p (p1 p2)
"Predicate for sorting processes P1 and P2."
@@ -1208,8 +1205,8 @@ proced-sort-p
(k2 (cdr (assq (car sorter) (cdr p2)))))
;; if the attributes are undefined, we should really abort sorting
(if (and k1 k2)
- (proced-xor (funcall (nth 1 sorter) k1 k2)
- (nth 2 sorter))))
+ (xor (funcall (nth 1 sorter) k1 k2)
+ (nth 2 sorter))))
(let ((sort-list proced-sort-internal) sorter predicate k1 k2)
(catch 'done
(while (setq sorter (pop sort-list))
@@ -1219,7 +1216,7 @@ proced-sort-p
(if (and k1 k2)
(funcall (nth 1 sorter) k1 k2)))
(if (not (eq predicate 'equal))
- (throw 'done (proced-xor predicate (nth 2 sorter)))))
+ (throw 'done (xor predicate (nth 2 sorter)))))
(eq t predicate)))))
(defun proced-sort (process-alist sorter descend)
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index 3bd99620d0..568479c822 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -2604,7 +2604,7 @@ idlwave-shell-enable-all-bp
(let ((bpl (or bpl idlwave-shell-bp-alist)) disabled modified)
(while bpl
(setq disabled (idlwave-shell-bp-get (car bpl) 'disabled))
- (when (idlwave-xor (not disabled) (eq enable 'enable))
+ (when (equiv disabled (eq enable 'enable))
(idlwave-shell-toggle-enable-current-bp
(car bpl) (if (eq enable 'enable) 'enable 'disable) no-update)
(push (car bpl) modified))
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index 614d73e23b..1b4b55c94f 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -8813,9 +8813,8 @@ idlwave-study-twins
;; FIXME: Dynamically scoped vars need to use the `idlwave-' prefix.
;; (defvar type)
-(defmacro idlwave-xor (a b)
- `(and (or ,a ,b)
- (not (and ,a ,b))))
+
+(define-obsolete-function-alias 'idlwave-xor 'xor "27.1")
(defun idlwave-routine-entry-compare (a b)
"Compare two routine info entries for sorting.
@@ -8919,17 +8918,17 @@ idlwave-routine-twin-compare
;; Now: follow JD's ideas about sorting. Looks really simple now,
;; doesn't it? The difficult stuff is hidden above...
(cond
- ((idlwave-xor asysp bsysp) asysp) ; System entries first
- ((idlwave-xor aunresp bunresp) bunresp) ; Unresolved last
+ ((xor asysp bsysp) asysp) ; System entries first
+ ((xor aunresp bunresp) bunresp) ; Unresolved last
((and idlwave-sort-prefer-buffer-info
- (idlwave-xor abufp bbufp)) abufp) ; Buffers before non-buffers
- ((idlwave-xor acompp bcompp) acompp) ; Compiled entries
- ((idlwave-xor apathp bpathp) apathp) ; Library before non-library
- ((idlwave-xor anamep bnamep) anamep) ; Correct file names first
- ((and idlwave-twin-class anamep bnamep ; both file names match ->
- (idlwave-xor adefp bdefp)) bdefp) ; __define after __method
- ((> anpath bnpath) t) ; Who is first on path?
- (t nil)))) ; Default
+ (xor abufp bbufp)) abufp) ; Buffers before non-buffers
+ ((xor acompp bcompp) acompp) ; Compiled entries
+ ((xor apathp bpathp) apathp) ; Library before non-library
+ ((xor anamep bnamep) anamep) ; Correct file names first
+ ((and idlwave-twin-class anamep bnamep ; both file names match ->
+ (xor adefp bdefp)) bdefp) ; __define after __method
+ ((> anpath bnpath) t) ; Who is first on path?
+ (t nil)))) ; Default
(defun idlwave-routine-source-file (source)
(if (nth 2 source)
diff --git a/lisp/simple.el b/lisp/simple.el
index e33709e8ad..bc5a802930 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -5847,8 +5847,7 @@ exchange-point-and-mark
(goto-char omark)
(cond (temp-highlight
(setq-local transient-mark-mode (cons 'only transient-mark-mode)))
- ((or (and arg (region-active-p)) ; (xor arg (not (region-active-p)))
- (not (or arg (region-active-p))))
+ ((equiv arg (region-active-p))
(deactivate-mark))
(t (activate-mark)))
nil))
diff --git a/lisp/strokes.el b/lisp/strokes.el
index 0c671c43ac..6edf58c7b6 100644
--- a/lisp/strokes.el
+++ b/lisp/strokes.el
@@ -1524,12 +1524,6 @@ strokes-xpm-char-bit-p
(or (eq char ?\s)
(eq char ?*)))
-;;(defsubst strokes-xor (a b) ### Should I make this an inline function? ###
-;; "T if one and only one of A and B is non-nil; otherwise, returns nil.
-;;NOTE: Don't use this as a numeric xor since it treats all non-nil
-;; values as t including `0' (zero)."
-;; (eq (null a) (not (null b))))
-
(defsubst strokes-xpm-encode-length-as-string (length)
"Given some LENGTH in [0,62) do a fast lookup of its encoding."
(aref strokes-base64-chars length))
diff --git a/lisp/subr.el b/lisp/subr.el
index f1a4e8bb29..e922fe739f 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -209,6 +209,26 @@ unless
(declare (indent 1) (debug t))
(cons 'if (cons cond (cons nil body))))
+(defsubst xor (cond1 cond2)
+ "Return the boolean exclusive-or of COND1 and COND2.
+If only one of the arguments is non-nil, return it; otherwise
+return nil."
+ (declare (pure t) (side-effect-free error-free))
+ (cond ((not cond1) cond2)
+ ((not cond2) cond1)))
+
+(defmacro equiv (&rest conditions)
+ "Return non-nil if all CONDITIONS are logically equivalent.
+That is, they are either all nil, or all non-nil. Arguments are
+evaluated in turn until one of them yields a logically different
+value; the remaining arguments are not evaluated. If no argument
+yields nil, return the last argument's value."
+ (if (cdr conditions)
+ `(if ,(car conditions)
+ (and ,@(cdr conditions))
+ (not (or ,@(cdr conditions))))
+ `(or ,(car conditions) t)))
+
(defmacro dolist (spec &rest body)
"Loop over a list.
Evaluate BODY with VAR bound to each car from LIST, in turn.
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 0d5dc0e1c0..a96c1bfd23 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -1770,7 +1770,7 @@ diff-find-approx-text
(if (> (- (car forw) orig) (- orig (car back))) back forw)
(or back forw))))
-(defsubst diff-xor (a b) (if a (if (not b) a) b))
+(define-obsolete-function-alias 'diff-xor 'xor "27.1")
(defun diff-find-source-location (&optional other-file reverse noprompt)
"Find out (BUF LINE-OFFSET POS SRC DST SWITCHED).
@@ -1783,7 +1783,7 @@ diff-find-source-location
SWITCHED is non-nil if the patch is already applied.
NOPROMPT, if non-nil, means not to prompt the user."
(save-excursion
- (let* ((other (diff-xor other-file diff-jump-to-old-file))
+ (let* ((other (xor other-file diff-jump-to-old-file))
(char-offset (- (point) (diff-beginning-of-hunk t)))
;; Check that the hunk is well-formed. Otherwise diff-mode and
;; the user may disagree on what constitutes the hunk
@@ -1909,7 +1909,7 @@ diff-apply-hunk
(insert (car new)))
;; Display BUF in a window
(set-window-point (display-buffer buf) (+ (car pos) (cdr new)))
- (diff-hunk-status-msg line-offset (diff-xor switched reverse) nil)
+ (diff-hunk-status-msg line-offset (xor switched reverse) nil)
(when diff-advance-after-apply-hunk
(diff-hunk-next))))))
@@ -1921,7 +1921,7 @@ diff-test-hunk
(pcase-let ((`(,buf ,line-offset ,pos ,src ,_dst ,switched)
(diff-find-source-location nil reverse)))
(set-window-point (display-buffer buf) (+ (car pos) (cdr src)))
- (diff-hunk-status-msg line-offset (diff-xor reverse switched) t)))
+ (diff-hunk-status-msg line-offset (xor reverse switched) t)))
(defun diff-kill-applied-hunks ()
@@ -1958,7 +1958,7 @@ diff-goto-source
(pop-to-buffer buf)
(goto-char (+ (car pos) (cdr src)))
(when buffer (next-error-found buffer (current-buffer)))
- (diff-hunk-status-msg line-offset (diff-xor reverse switched) t))))
+ (diff-hunk-status-msg line-offset (xor reverse switched) t))))
(defun diff-current-defun ()
@@ -2253,7 +2253,7 @@ diff-delete-trailing-whitespace
(interactive "P")
(save-excursion
(goto-char (point-min))
- (let* ((other (diff-xor other-file diff-jump-to-old-file))
+ (let* ((other (xor other-file diff-jump-to-old-file))
(modified-buffers nil)
(style (save-excursion
(when (re-search-forward diff-hunk-header-re nil t)
diff --git a/lisp/windmove.el b/lisp/windmove.el
index ab47565dfa..f5f51480db 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -592,7 +592,7 @@ windmove-display-in-direction
the prefix argument is reversed.
When `switch-to-buffer-obey-display-actions' is non-nil,
`switch-to-buffer' commands are also supported."
- (let* ((no-select (not (eq (consp arg) windmove-display-no-select))) ; xor
+ (let* ((no-select (xor (consp arg) windmove-display-no-select))
(old-window (or (minibuffer-selected-window) (selected-window)))
(new-window)
(minibuffer-depth (minibuffer-depth))
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 06db8f5c90..f834c6a862 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -125,6 +125,28 @@ subr-test-when
(should (equal (macroexpand-all '(when a b c d))
'(if a (progn b c d)))))
+(ert-deftest subr-test-xor ()
+ "Test `xor'."
+ (should-not (xor nil nil))
+ (should (eq (xor nil 'true) 'true))
+ (should (eq (xor 'true nil) 'true))
+ (should-not (xor t t)))
+
+(ert-deftest subr-test-equiv ()
+ "Test `equiv'."
+ (should (equiv))
+ (should (equiv nil))
+ (should (equiv nil nil))
+ (should (equiv nil nil nil))
+ (should (eq (equiv 'true) 'true))
+ (should (eq (equiv t 'true) 'true))
+ (let (x)
+ (should-not (equiv nil t (setq x t)))
+ (should-not (equiv t nil (setq x t)))
+ (should-not x)
+ (should (eq (equiv t t (setq x 'true)) 'true))
+ (should (eq x 'true))))
+
(ert-deftest subr-test-version-parsing ()
(should (equal (version-to-list ".5") '(0 5)))
(should (equal (version-to-list "0.9 alpha1") '(0 9 -3 1)))
--
2.20.1
[-- Attachment #2: Type: text/plain, Size: 541 bytes --]
"Basil L. Contovounesios" <contovob@tcd.ie> writes:
> Oleh Krehel <oleh@oremacs.com> writes:
>
>> Should we figure out where to put the "main" `xor' and declare the rest as
>> obsolete aliases?
>
> Yes please! I've had a patch to this effect sitting on a local branch
> for a while now. Will touch it up and send soon.
Now attached.
It defines xor using defsubst instead of define-inline, so that it can
be included in subr.el. Would defun be preferred instead?
It also includes Mattias' equiv suggestion.
WDYT?
Thanks,
--
Basil
next prev parent reply other threads:[~2019-07-24 22:17 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-22 18:48 7 logical-xor implementations in source tree Oleh Krehel
2019-07-22 21:47 ` Basil L. Contovounesios
2019-07-24 22:17 ` Basil L. Contovounesios [this message]
2019-07-24 23:15 ` Stefan Monnier
2019-07-24 23:44 ` Basil L. Contovounesios
2019-07-25 12:07 ` Mattias Engdegård
2019-07-25 17:28 ` Paul Eggert
2019-07-25 17:46 ` Mattias Engdegård
2019-07-28 7:09 ` Philippe Schnoebelen
2019-07-28 8:04 ` Alan Mackenzie
2019-07-28 19:43 ` Marcin Borkowski
2019-07-30 9:36 ` Alan Mackenzie
2019-07-30 10:57 ` Philippe Schnoebelen
2019-07-30 11:28 ` Andy Moreton
2019-07-30 12:34 ` Stefan Monnier
2019-07-30 14:25 ` Barry Fishman
2019-07-31 3:16 ` Richard Stallman
2019-07-31 15:20 ` Barry Fishman
2019-07-31 15:42 ` Stefan Monnier
2019-07-31 20:22 ` Basil L. Contovounesios
2019-07-31 21:15 ` Michael Heerdegen
2019-07-31 22:28 ` Mattias Engdegård
2019-07-31 23:39 ` Basil L. Contovounesios
2019-08-02 10:29 ` Mattias Engdegård
2019-08-02 10:59 ` Basil L. Contovounesios
2019-08-06 11:58 ` Mattias Engdegård
2019-07-31 20:31 ` Michael Heerdegen
2019-07-31 21:38 ` Drew Adams
2019-07-31 22:03 ` Drew Adams
2019-07-31 22:05 ` Basil L. Contovounesios
2019-07-31 23:20 ` Drew Adams
2019-08-01 0:09 ` Basil L. Contovounesios
2019-07-31 17:12 ` Marcin Borkowski
2019-07-23 8:39 ` Andy Moreton
2019-07-23 9:08 ` Basil L. Contovounesios
2019-07-23 9:14 ` Mattias Engdegård
2019-07-23 10:26 ` Andy Moreton
2019-07-23 10:40 ` Andreas Schwab
2019-07-23 12:11 ` Andy Moreton
2019-07-23 13:20 ` Basil L. Contovounesios
2019-07-23 13:54 ` Andy Moreton
2019-07-24 22:21 ` Basil L. Contovounesios
2019-07-23 10:44 ` Basil L. Contovounesios
2019-07-23 11:01 ` Yuri Khan
2019-07-25 21:46 ` Juri Linkov
2019-07-23 11:24 ` Noam Postavsky
2019-07-23 12:38 ` Stefan Monnier
2019-07-23 16:41 ` Mattias Engdegård
2019-07-23 17:12 ` Eli Zaretskii
2019-07-23 17:48 ` Paul Eggert
2019-07-23 19:45 ` Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87sgqvoz5c.fsf@tcd.ie \
--to=contovob@tcd.ie \
--cc=emacs-devel@gnu.org \
--cc=oleh@oremacs.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.