Subject: Re: bug#78719: 30.1; [PATCH] Add functions `string-common-prefix' and `string-try-completion'

From: Phil Sainty <[email-masked]>
Date: Sun, 06 Jul 2025 00:05:01 +1200

On 2025-06-29 18:05, Eli Zaretskii wrote:
> Btw, the changes for the manual have the argument list wrong.

Thanks; fixed.

> Also, this part:
> 
>   If COLLECTION contains exactly one string, return that string.
> 
> left me wondering whether this will happen even if that single string
> doesn't satisfy the filtering criteria.

Good point; I've clarified this.

> My single high-level gripe about this changeset is that it ended up
> to be too tied up with completion.  AFAIU, the original intent was
> to provide an API for finding the longest common prefix of a list of
> strings.  With that concept in sight, STRING should have been a
> mandatory argument (perhaps an empty string), and the fact that this
> is based on the completion machinery should have been an
> implementation detail.

I don't think STRING should be mandatory.  If you're wanting the
longest prefix from an unfiltered collection (which I think will be a
very common use-case for the function), it's unnecessarily awkward to
need to also pass an explicit empty string argument when it could be
left as an optional one.  Indeed, I'd say that not *needing* that
argument is one of the benefits of the new function, vs using
`try-completion' (which does require it).

> The REGEXP-LIST and PREDICATE would not be needed, either.  By
> contrast, what we have instead is a variant of try-completion, and
> both the documentation and the API itself are advertising the
> completion-based nature of the function too loudly to my palate,
> starting from the argument named COLLECTION.  Why would we need yet
> another variant of try-completion?

If `string-common-prefix' was not based on `try-completion' and we
needed to write all of the functionality from scratch, then I would
not be pushing to include and document the additional features.

It is based on `try-completion' though (for the good reason that
`try-completion' is already extremely efficient at performing this
task), and that has some ramifications for the new function:

1. It will support the same COLLECTION data types as `try-collection'.

2. All of the filtering features of `try-collection' are available.

I just see no reason to hide or suppress any of these things.  Each of
the filtering options may very well prove useful to users -- and they
are already implemented!  I don't know why we wouldn't provide access
to them.  It may be a somewhat advanced option feature set, but it's
not an /unreasonable/ feature set for this function to have -- each
filter would be useful in different circumstances, so it seems to me
like a perfectly useful thing to support, and it's so easy to do so.

> both the documentation and the API itself are advertising the
> completion-based nature of the function too loudly to my palate

We could safely drop the final sentence "This function is similar
to `try-completion', but always returns a string.", but I think the
previous paragraph should remain.

I feel the documentation should reflect the functionality, and the
functionality in this case is dictated by `try-completion', so I don't
see a way to avoid mentioning it.  I'd prefer the documentation to be
clear about what it does than to pretend that `string-common-prefix'
is an isolated function.

> So maybe we should make this API simpler, so it could do its main
> job without requiring such a large and complicated doc string, and
> leave the rest to try-completion?

Again, my personal feeling is that the filtering is reasonable, so
I'm in favour of keeping it.

I don't like "leave the rest to try-completion" because try-completion
is really awkward to use outside of a completion context.  The reasons
for adding the new function were:

1. Discoverability; `try-completion' is a very non-obvious name for
anyone working with strings rather than completion, whereas the
`string-common-prefix' name will be very easily found.

2. Ease of use: `try-completion' requires you to jump through hoops
in order to deal with its non-string return values, whereas the new
function deals with those edge cases to return what's useful for
working with strings.

If we force people to go back to `try-completion' to get the extra
functionality, we also force them to jump through those hoops, whereas
the new API is easy to use in all cases.

That said, my first implementation was almost exactly that -- one
simple function for the basic case which made almost no reference to
completion at all, and a second function which was /explicitly/ the
same as `try-completion' /except/ for taking care of the return-value
hoop-jumping.  With that approach we had what you've just suggested
minus the inconvenience.  No one liked the two-function approach,
though, so I merged the two functions into one.

I like the current version better, but going back to that first
implementation is certainly an option.

Another two-function alternative would be for the current
implementation to become the 'complex' version of the function,
and then have a simple version for common use.  Something like
`string-common-prefix' and `string-common-prefix-filtered'.

-Phil