Subject: Re: bug#65797: `buffer-match-p` should not use `func-arity`

From: Philip Kaludercic <[email-masked]>
Date: Tue, 19 Sep 2023 08:34:57 +0000

Stefan Monnier <[email-masked]> writes:

>>> - Deprecate the feature with no replacement (i.e. users will have
>>>   to use a (lambda (x y) (foo x)) wrapper to drop the second arg if they
>>>   were using the feature).  That's my favorite option at this point.
>>
>> I would be disappointed to see this path taken, since part of my hope
>> with buffer-match-p was that it could be used in project.el as well
>> (allowing this to be a thing is one of the reasons I started working on
>> Compat).
>
> I don't understand: you just told me you have no examples of places
> where single-arg functions are concretely useful.

My apologies, to clarify: I don't know of any example where it is
currently used (project.el has a separate implementation), but this
would be one example where a single-argument invocation would be useful.

> So, assuming `buffer-match-p` is used in many other things, like
> `project.el`, do you have examples where the feature of choosing between
> calling sometimes with one arg and sometimes with two would be
> useful/handy?

That is a different matter.  Usually if buffer-match-p is not passed an
argument via ARG, then all the function calls would also just have a
single argument.  But in other examples, such as display-bufffer-alist
where ARG is non-nil, the user might want to fall back onto ignoring
ARG.  OTOH the difference between

  (lambda (buf) ...)

and

  (lambda (buf _) ...)

is not that great either.  So one could invoke the function with two
arguments if ARG is non-nil, and otherwise just with one.

> [ BTW, changing the code to use `&rest args` instead of `&optional arg`
>   would help for this, right?  ]

How come?

>>> - Replace it with some alternative (e.g. provide two different syntaxes
>>>   for functions, one for functions that expect all args and one for
>>>   functions that only take a single arg).
>>
>> So `(arg1 ,(lambda (x) ...)) and `(arg2 ,(lambda (x y) ...))?
>
> No, I was more thinking of `(pred1 FOO)` vs `(pred FOO)` or using just
> `FOO` for those functions which take all the arguments and `[FOO]` for
> those functions which only accept a single argument, or any other
> suitable "annotation".
> Or you could use an OClosure which carries some explicit user-provided
> arity info with it.

How would that look like?

>>> - Live with the occasional breakage and bug reports like the current one.
>> The issue here was related to advising a function.  And you are saying
>> there is no way around this, not even by annotating the function symbol
>> with the initial arity before it is advised.
>
> No, we can fix this case with some ad-hoc hack.
> But we can't fix every case once and for all, so the hack ends up being
> very costly compared to its benefit.
>
> The general rule is that you should never look at a function to decide
> how to call it (more generally, you should never look at a function
> beyond testing `functionp` or `commandp` (other than for debugging and
> the like), you should only call it).

OK, I see, I was not familiar with this principle.

>         Stefan