unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: "Mattias Engdegård" <mattiase@acm.org>
To: Paul Eggert <eggert@cs.ucla.edu>
Cc: Pip Cet <pipcet@gmail.com>, Emacs developers <emacs-devel@gnu.org>
Subject: Re: Bug#38708: eq vs eql in byte-compiled code
Date: Wed, 1 Jan 2020 13:38:57 +0100	[thread overview]
Message-ID: <E783F93A-915D-4467-B308-17AC32639B35@acm.org> (raw)
In-Reply-To: <8cd1b5b2-b94e-ce64-0d70-c1b8b012d685@cs.ucla.edu>

[-- Attachment #1: Type: text/plain, Size: 2124 bytes --]

31 dec. 2019 kl. 18.38 skrev Paul Eggert <eggert@cs.ucla.edu>:

> One possible compromise would be to duplicate only bignums in the emacs-27
> branch, while reserving flonum deduplication for the master branch. This would
> help a bit with now-incorrect code that uses eq to compare bignum values, while
> not introducing flonum "paradoxes".

The flonum/bignum deduplication patch is only in master at this point. If you think it emacs-27 would benefit from a version of it that specifically excludes flonums, this could of course be arranged.

In general, though, my impression is that the likelihood of any trouble in practice is nil (speaking as the author of the change, of course).

More important is how to present equality semantics to the user, through documentation, NEWS, and examples. This includes:

- What 'eq' can be used for: what we recommend, and what we guarantee.
- Which equality relation to use and when: eq, eql, equal, =, string-equal, etc.

For example, while we have to guarantee that 'eq' works for fixnums for compatibility, it may be unwise to give this fact prominence in the documentation. One of the benefits of bignums is that users no longer have to worry about fixnum ranges in most cases. The standard rule should be not to use 'eq' for numbers of any kind.

Whether to specifically mention characters as eq-comparable is a matter of judgement. (Neither CL nor Scheme guarantee that characters can be used with eq/eq?.) Of course my own code is littered with eq for characters, but do as I say...

Attached is a proposed documentation patch for emacs-27. While not perfect, it should at least be an improvement (and fixes at least one error).

> How about going a bit further, and globally deduplicating all flonums and
> bignums that result from low-level text-to-number conversion and module imports?
> That conversion is slow and/or rare already, and if we're lucky deduplication
> wouldn't make things noticeably slower and wouldn't be much work.

Maybe, but wouldn't that slow down reading .elc files (and still not shorten individual constant vectors)?


[-- Attachment #2: 0001-Clarify-eq-on-numbers.patch --]
[-- Type: application/octet-stream, Size: 5209 bytes --]

From fdb4519ca621fbfd893f23f62ef0b97379f9c8a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Wed, 1 Jan 2020 13:06:39 +0100
Subject: [PATCH] Clarify 'eq' on numbers

* doc/lispref/numbers.texi (Integer Basics):
* doc/lispref/objects.texi (Integer Type, Equality Predicates):
* etc/NEWS:

Recommend that 'eq' not be used to compare numbers, and fix some
erroneous or misleading examples.  See discussion starting at
https://lists.gnu.org/archive/html/emacs-devel/2019-12/msg00856.html
and bug#38708.
---
 doc/lispref/numbers.texi |  2 ++
 doc/lispref/objects.texi | 32 +++++++++++++++++---------------
 etc/NEWS                 |  3 ++-
 3 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index e952980f26..1c6f8ae7be 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -41,6 +41,8 @@ Integer Basics
 Some functions in Emacs accept only fixnums.  Also, while fixnums can
 always be compared for numeric equality with @code{eq}, bignums
 require more-heavyweight equality predicates like @code{eql}.
+To avoid any concern about fixnum ranges, use @code{eql} or @code{=}
+for comparing numbers.
 
   The range of values for bignums is limited by the amount of main
 memory, by machine characteristics such as the size of the word used
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 4be2eb6918..a0ce7aebd0 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -270,7 +270,9 @@ Integer Type
 @code{eql} or @code{=}.  To test whether an integer is a fixnum or a
 bignum, you can compare it to @code{most-negative-fixnum} and
 @code{most-positive-fixnum}, or you can use the convenience predicates
-@code{fixnump} and @code{bignump} on any object.
+@code{fixnump} and @code{bignump} on any object.  Most of the time,
+however, it is more convenient to ignore the difference and use
+@code{eql} or @code{=} for comparing any kind of number.
 
   The read syntax for integers is a sequence of (base ten) digits with an
 optional sign at the beginning and an optional period at the end.  The
@@ -2167,19 +2169,20 @@ Equality Predicates
 This function returns @code{t} if @var{object1} and @var{object2} are
 the same object, and @code{nil} otherwise.
 
-If @var{object1} and @var{object2} are fixnums with the same value,
-they are considered to be the same object (i.e., @code{eq} returns
-@code{t}).  If @var{object1} and @var{object2} are symbols with the
+Numbers in general do not have an object identity and therefore cannot
+be compared reliably using @code{eq}.  While fixnums (and characters)
+with the same value are considered to be the same object (i.e.,
+@code{eq} returns @code{t}), this is not true for bignums and floats.
+For maximum portability and robustness, avoid using @code{eq} for
+numbers (@pxref{Comparison of Numbers}).
+
+If @var{object1} and @var{object2} are symbols with the
 same name, they are normally the same object---but see @ref{Creating
 Symbols} for exceptions.  For other types (e.g., lists, vectors,
 strings), two arguments with the same contents or elements are not
 necessarily @code{eq} to each other: they are @code{eq} only if they
 are the same object, meaning that a change in the contents of one will
 be reflected by the same change in the contents of the other.
-For other types of objects whose contents cannot be changed (e.g.,
-bignums and floats), two arguments with the same contents might or might not be
-the same object, and @code{eq} returns @code{t} or @code{nil}
-depending on whether the Lisp interpreter created one object or two.
 
 @example
 @group
@@ -2188,26 +2191,25 @@ Equality Predicates
 @end group
 
 @group
-(eq 456 456)
+(eq ?A ?A)
      @result{} t
 @end group
 
 @group
 (eq 3.0 3.0)
      @result{} t @r{or} nil
-;; @r{The result is implementation-dependent.}
+;; @r{Equal floats may or may not be the same object.}
 @end group
 
 @group
-(eq "asdf" "asdf")
+(eq (make-string 3 ?A) (make-string 3 ?A))
      @result{} nil
 @end group
 
 @group
-(eq "" "")
-     @result{} t
-;; @r{This exception occurs because Emacs Lisp}
-;; @r{makes just one multibyte empty string, to save space.}
+(eq "asdf" "asdf")
+     @result{} t @r{or} nil
+;; @r{Equal string constants may or may not be the same object.}
 @end group
 
 @group
diff --git a/etc/NEWS b/etc/NEWS
index a8c8e2763e..efcd63e35c 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2879,7 +2879,8 @@ All the arithmetic, comparison, and logical (a.k.a. "bitwise")
 operations where bignums make sense now support both fixnums and
 bignums.  However, note that unlike fixnums, bignums will not compare
 equal with 'eq', you must use 'eql' instead.  (Numerical comparison
-with '=' works on both, of course.)
+with '=' works on both, of course.)  To avoid mistakes, we recommend
+that you do not use 'eq' for comparing numbers at all.
 
 Since large bignums consume a lot of memory, Emacs limits the size of
 the largest bignum a Lisp program is allowed to create.  The
-- 
2.21.0 (Apple Git-122.2)


  reply	other threads:[~2020-01-01 12:38 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-31 15:07 Bug#38708: eq vs eql in byte-compiled code Pip Cet
2019-12-31 15:51 ` Andrea Corallo
2019-12-31 16:05 ` Mattias Engdegård
2019-12-31 17:38 ` Paul Eggert
2020-01-01 12:38   ` Mattias Engdegård [this message]
2020-01-02  8:38     ` Paul Eggert
2020-01-02 17:26       ` Mattias Engdegård
2020-01-04 19:55         ` Stefan Monnier
2020-01-22 10:56       ` Mattias Engdegård
2020-01-25  0:59         ` Paul Eggert
2020-01-01 15:45   ` Stefan Monnier
2020-01-02  7:52     ` Paul Eggert
2020-01-02 12:27       ` Pip Cet
2020-01-02 23:12         ` Paul Eggert
2020-01-02 13:48       ` Eli Zaretskii
2020-01-04 18:54       ` Stefan Monnier
2020-01-04 19:33         ` Paul Eggert
2020-01-04 19:49           ` 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

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E783F93A-915D-4467-B308-17AC32639B35@acm.org \
    --to=mattiase@acm.org \
    --cc=eggert@cs.ucla.edu \
    --cc=emacs-devel@gnu.org \
    --cc=pipcet@gmail.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 public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).