> * zip(strict=True) +1
> * zip(mode='strict') -0
> * itertools.zip_strict() -0.5
> * zip.strict() -1 (but really, I'd like to make this -1e10)
I spent a significant amount of time and mental energy explaining in
detail why a boolean flag is a poor API and is objectively the wrong
interface here. This is not just a matter of personal taste: there are
reasons why a flag is wrong here.
Clearly it is not the objective truth, otherwise you would have an easier way convincing everyone. :-)
Flags are for combining independent and orthogonal settings which can be
combined. This is not such a feature. I think it is objectively the
worst API on the table here, for reasons already discussed.
Sorry, Ihave to object to your use of the word "objectively". Clearly what's worst depends upon one's perspective.
- Your preferred option makes the strict zip version a second-class
citizen of the language;
With any other option it will still be that -- "zip" is the dominant name here, (a) because it's so short, (b) because it's somehow a memorable word, (c) because it's been around for 20 years.
- your preferred option is the least open to future enhancements;
Given zip's stability, I doubt there will be a lot of other future enhancements any time soon. In Python's culture, boolean flag is the most common way to modify the behavior of a function. The reasons have to do with tradition (lots of existing APIs use this pattern) as well as ease of implementation (*also* in the Zen!), and also with how people *think* about certain APIs. Zip-strict is "like zip, but strict(er) in its requirements".
- your most hated option is the one which follows the Zen of Python
the most closely (namely, the koan about having more namespaces);
I'm sorry, I'm not buying this. While for *classes* , alternate constructors are a well-known pattern (dict.from_keys(), datetime.fromtimestamp(), etc.), for *functions* (and almost everyone thinks of zip as a function -- including the
docs!) this pattern is uncommon, and awkward to implement. (You have to write it as a separate function and then make that function a function attribute of the first function.)
It is also quite uncommonly found -- no other builtin *function* uses it, and only one function in itertools uses it. I know there are 3rd party frameworks that use this convention, and as a general convention for a framework it's fine. But for an existing builtin function I think a lot of people will do a double-take when they read it in someone else's code (thinking it may be a typo). Whereas nobody will lift an eyebrow when they see zip(a, b, strict=True) -- even if they've never heard of it, they immediately know that it's a modification to the zip() behavior they know.
- and is the most object-oriented solution (it's effectively a method);
That's not even an argument. (It's
abuse. :-)
- and most importantly you explicitly *oppose* every alternative API,
giving them negative preferences; you would rather not have this zip
variant at all than have an interface other than a boolean flag.
I think that's a fallacy. Opposing a proposal is not the same as saying you would rather have nothing than that. It simply expresses a strong negative reaction.
If I needed this function[1], I'd accept it even if it were spelled
`xyghasx.peyahc.flihaj()` and required me to set a global variable to
make it work. So I can't help but interpret your total opposition to
every other interface as a strong sign that you don't really need this
zip variant at all. If your opinion is typical, perhaps we should just
reject the PEP.
Another straw-man. My personal vote, for example, is +1 on zip(strict=True) and -1 on zip.strict(). But if the SC chooses the latter, I'll happily use it.
Could you explain why you believe a bool flag is the only
suitable interface? Objective reasons preferred please.
An unreasonable request. I've tried to explain above why in the context of where we are (Python 3.9) I find it the best option.
The same goes for everyone else who gave a vote. If you have an
objective reason for wanting this strict zip function to be a second
class citizen that cannot be easily extended in the future, then please
explain why.
It will *always* be a second class citizen, no matter how you name it, unless you change the behavior of zip(), which is off the table.
[1] I don't think I do. If I had my preference, thinking only of my own
needs, I'd probably reject the PEP. But I acknowledge that others seem
to need it.
Then I really have to wonder why you are so invested in convincing everyone that your proposal is the only one that's objectively acceptable.
Finally, I have to clarify something. In the past I've often said that if you're thinking to introduce a boolean flag to an API that's always going to be passed as a constant (if at all), you're probably better off with a separate function. This would seem to be such a case. Yet I am not following my advice. Why? (a) It's a rule of thumb, and in this case I find zip_strict() just a bit less clean than zip(strict=True); an relegating it to itertools.zip_strict() makes it a lot less attractive. And (b) That rule is most important when the flag affects the *return type* of a function. This is because static checkers have a hard time with such APIs. (Almost-example: open(..., "rb") returns an IO[bytes] while open(..., "r") returns an IO[str].)
PS. Why wasn't a new builtin zip_strict() on the menu? I think I would have given it at least +0.5, because of this rule of thumb.
--