all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Philipp Stephani <p.stephani2@gmail.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: emacs-devel@gnu.org
Subject: Re: Should records be able to mimic primitive types?
Date: Sun, 24 Sep 2017 14:47:56 +0000	[thread overview]
Message-ID: <CAArVCkTRf0aU7NZV+wOQ7U8MLKA6=vqnf_nOj_MmBUXSL=R-2A@mail.gmail.com> (raw)
In-Reply-To: <jwv4lvfepn0.fsf-monnier+Inbox@gnu.org>

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

Stefan Monnier <monnier@iro.umontreal.ca> schrieb am Fr., 16. Juni 2017 um
21:07 Uhr:

> >> Will all 3 steps ever occur at the same time?
> > I don't think this is an important question.
>
> But in the absence of the combination of those 3 steps, your check will
> make no difference.  Are you saying that you don't think "whether my
> check makes a difference" is an important question?
>

It does make a difference. It's important for specifications to be precise
and unsurprising, no matter whether a certain case is frequent or not.


>
> > The important point is: Previously, there were invariants such as
> > (integerp x) == (eq (type-of x) 'integer) or that prin1 would only
> > generate #s(hash-table ...) for actual hash tables.  Now these
> > invariants are broken.
>
> Every patch we install changes an "invariant" (except for cosmetic
> patches, changes to the build system, ...).
>
> So we can't take such an absolute position, if we want to keep
> developing Emacs (including fixing bugs): we necessarily have to judge
> which invariants are worthy of being preserved and which ones aren't.
>

True, but such changes need to be considered very carefully, and we need to
state explicitly which invariants can be broken without notifying anybody
(e.g. introducing new functions in the global namespace), which can be
broken by listing them in the NEWS file under "Breaking changes" (such as
removing a function), and which invariants cannot be broken.
The change being discussed here is at least in the second category. I would
argue it is even in the third category: it breaks invariants around
fundamental ELisp types for no good reason.


> E.g. if we ever get good support for bignums, we'll likely have to break
> your first invariant.
>

We can't do that. Bignum support would either have to be completely
transparent (which would make `eq' more complex), or they should be a
completely separate type.


>
> Also we have to distinguish between breaking an invariant and not
> enforcing it.  I do consider an Elisp code which creates a record of
> type `integer` as a bug, but I don't think it's worth this particular
> effort to enforce it.
>

This doesn't work: if it's not an explicit error, then people will start
relying on it ("Hyrum's law"). We need to enforce our specifications,
otherwise they aren't specifications.


>
> Even with your extra check the above two invariants won't always hold.
> I can trivially break the first one with some add-advice on type-of.
> Should we add another check to prevent breaking the "invariant" in that
> other way?  The second can be broken without even using an advice on
> `prin1` simply by creating a record of type (make-symbol "hash-table").
> Should we also add yet another check to try and avoid this other way to
> break your "invariant"?
>

No. Even though I dislike the advice functionality, would want to ban it
for primitive functions, and think that it's dangerously overused, it (or
rather the underlying `fset' primitive) is a part of the language, just
like reflection in Java. Users should definitely be warned to steer clear
from fset and its wrappers except for specialized uses such as mocking, but
its existence shouldn't affect other development: Code may always assume
that `fset' hasn't been called on any of the named functions it calls. If
that assumption is broken, it's the burden of the code that breaks it.


>
> > But there's a discontinuity between "invariant is guaranteed" and
> > "invariant is almost always guaranteed": the latter is identical to
> > "invariant is not guaranteed at all".
>
> In Elisp, the general rule is that thanks to the dynamic nature of the
> language, there are precious few invariants which really always hold.
> E.g. as soon as your "invariant" calls a function by name, you're
> exposed to breakage via the advice mechanism.
>
> So, in a sense, Elisp is a landmine just like C.
>

Most languages have escape hatches (e.g. reflection in Java). That doesn't
mean we should accept them as a given or introduce more them for no good
reason.


>
> > Yes, absolutely.  I don't care whether it's rare or hypothetical, it
> breaks
> > an invariant, and invariants must not be broken.
>
> You might like to try Agda or Coq, but Elisp will inevitably disappoint
> you in this area.
>
>
As mentioned, such invariants can be written conditionally to no `fset'
calls happening. If `fset' is used, all invariants are trivially broken.

[-- Attachment #2: Type: text/html, Size: 6051 bytes --]

  reply	other threads:[~2017-09-24 14:47 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-04 22:00 Should records be able to mimic primitive types? Paul Eggert
2017-04-05  1:09 ` Stefan Monnier
2017-04-08 15:09   ` Philipp Stephani
2017-04-08 17:57     ` Stefan Monnier
2017-05-01 11:35       ` Philipp Stephani
2017-05-01 12:03         ` Stefan Monnier
2017-06-10 11:39           ` Philipp Stephani
2017-06-10 12:43             ` Eli Zaretskii
2017-06-12 15:07               ` Philipp Stephani
2017-06-12 17:00                 ` Eli Zaretskii
2017-06-12 17:15                   ` Stefan Monnier
2017-06-12 17:22                     ` Eli Zaretskii
2017-06-12 17:47                       ` Stefan Monnier
2017-06-12 17:40       ` Stefan Monnier
2017-06-16 18:42         ` Philipp Stephani
2017-06-16 19:07           ` Stefan Monnier
2017-09-24 14:47             ` Philipp Stephani [this message]
2017-09-24 16:44               ` 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='CAArVCkTRf0aU7NZV+wOQ7U8MLKA6=vqnf_nOj_MmBUXSL=R-2A@mail.gmail.com' \
    --to=p.stephani2@gmail.com \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /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.