Subject: Re: bug#72328: [PATCH] Nested backquote in pcase

From: Eli Zaretskii <[email-masked]>
Date: Thu, 08 Aug 2024 08:57:11 +0300

> From: Thuna <[email-masked]>
> Cc: Eli Zaretskii <[email-masked]>, [email-masked],
>  [email-masked]
> Date: Wed, 07 Aug 2024 19:34:32 +0200
> 
> What I question is not Eli's intentions or reasons, but the consequences
> of complying with those requests: I fear that the moment I start
> defending and giving justifications for the existence of macroexp-null,
> this report will forever be reduced to just a "companion patch" whose
> sole purpose is to make a later patch *look* nice.  My concern is that
> this will end up the same way me showing no code in melpa would be
> effected by this patch did - with my case being hurt on false grounds.

You make it sound as if there's some hidden agenda in this discussion.
There isn't.

> I have evidently been unable to get my point across, so let me try to
> explain it yet again: The "broader context" has no effect on the
> decision to use pcase in macroexp-null, you might as well be asking my
> why I used cond.  I use pcase in macroexp-null because for pattern
> matching it is by far the best tool there is and it makes for a much
> more readable and extensible code than
> 
>   (defun macroexp-null (exp)
>     "Return non-nil if EXP will always evaluate to nil.
>   This form does not take non-local exits or side-effects into account."
>     (or (member exp '(nil 'nil #'nil `nil))
>         (and (eq '\` (car-safe exp))
>              (length= exp 2)
>              (eq '\, (car-safe (nth 1 exp)))
>              (length= (nth 1 exp) 2)
>              (macroexp-null (nth 1 (nth 1 exp))))))
> 
> Furhermore, even if the resulting discussion concludes that
> macroexp-null should exist, that does not mean anything about this
> change; I have already demonstrated that the program can be written
> without it[1].  And the reverse implication is true: This patch can be
> accepted without macroexp-null.  In fact, it is a stronger implication:
> This patch can be accepted without ever acknowledging the existence of
> macroexp-null.
> 
> Given these two are separate things that do not need each other, and the
> example alone demonstrates the value of this new behavior in this
> specific situation, the continued inquiry on a justification can only
> bring about a single result: If I somehow fail to convince people that
> macroexp-null should exist, this makes a case against this patch.  The
> opposite will not be true however (if I convince you that macroexp-null
> should exist will you not simply tell me to use the version which works
> pre-patch?).
> 
> And let me also mention again why I think that this is a genuine
> improvement: You currently cannot match against a nested backquote
> object in any sane way.  The pattern you need to match against the
> unevaluated form ``(,,<integer>) is
>   `(,'\` (,'\` (,'\, (,'\, ,(pred integerp)))))
> and... how is this not considered a problem?  That this thing works at
> all can only really be thought of as a coincidence, and it explicitly
> relies on `foo being (\` foo), which I would personally consider an
> internal implementation detail not to be used by outside code.
> 
> There is a genuine loss with switching over to the new behavior: We run
> into the same issue as before when matching against an unevaluated form
> ``(,<symbol> ,,<integer>).
> 
> This is also why I want to have more discussion about the patch itself:
> The current behavior is bad at actually matching backquote objects as
> obtained by a single quasiquote macro, but the proposed behavior is bad
> at matching backquote objects obtained by multiple different-but-close
> quasiquote macros[2].  It is very likely that the result of that
> discussion will end up changing the way this patch actually works and
> maybe even result in the original behavior being maintained in the first
> place.

I think we all agree that your suggestion has some advantages in some
situation.  We also all agree that the problem you are trying to solve
is solvable already by other means, so it isn't like the problem
doesn't have workarounds, and the workarounds are not in general
terribly kludgey or inconvenient.

So justification for introducing such change in behavior is actually
the main point that needs to be discussed, because it will be a main
factor in the decision whether we want to install such a change.  And
the justifications that we are interested to hear are the situations
where using the available behavior would cause such significant
inconvenience or unclean code that having this new behavior would
avoid.  Then we will have to decide whether those situations are
important enough for us to risk the incompatibilities, complicate the
documentation, add backward-compatibility shims, etc. -- all of which
make Emacs slightly more complex and slightly harder to maintain.

This process and these considerations are inherent to the maintainers'
decision process when a change is proposed that means incompatible
behavior changes in Emacs.  Talking about the advantages alone doesn't
cut it.