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

From: Thuna <[email-masked]>
Date: Wed, 07 Aug 2024 19:34:32 +0200

>> I don't see how we can discuss whether this patch has enough benefits to
>> clear the hurdle of backwards-incompatibility if you are not willing to
>> engage with the discussion of what this patch's benefits *are* to begin
>> with.
>
> He sees that of course, but it is not what he has asked for because it
> is obviously not enough.

It may not be enough but it is a necessary step.  I am currently having
to caveat all usage of the word "improvement" with either a weakener
like "IMO" or a conditional like "if this is considered an improvement".
Having to repeatedly try to appease implicit, unstated, and
unchallangable contentions is rather tiring.

> So I suggest to avoid meta discussions about what we expect and
> how others should behave and, even if it sucks, try to answer Eli's
> questions without questioning his reasons and intentions all the time.

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.

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.

[1] With or without pcase, though in this instance I am referring to the
with-pcase version I provided in my previous messages.

[2] You can only obtain an unevaluated form ```(,<symbol> ,,,<integer>)
via an evaluated form like ````(,<symbol> ,,,,<integer-returning-form>)
where <symbol> is a fixed symbol.  If the pcase pattern is matching
against all possible <symbol> objects, that means that the objects it is
matching must be coming from different quasiquote forms.