4 ms·
> which just seems like a really weird use case I think quite the opposite: What you expected seems unnecessary to me because that is already easy to do with t
by jackewiehose 8y ago
> which just seems like a really weird use case
I think quite the opposite: What you expected seems unnecessary to me because that is already easy to do with that if-statement in your example.
On the other hand, to accomplish this "for-else" you would have to do something like this:
found = false
for x in list:
if ...:
found = true
if not found:
...
While writing this example I noticed that I also could make good use of the negativ: Something like
for x in list:
...
then:
...
- contravariant 8y agoTo achieve the for else I suggested for general generators requires a similar pattern to your suggestion so both of them save equal amounts of complexity. However I'm struggling to find a use case for the python for-else definition where you don't end up doing something like 'result=something; break' anyway. What would be the point of breaking if you don't have any results? And if you have such a situation, wouldn't an exception make more sense? Conversely to check if an iterator is non-empty you need to set a boolean to true, and you can't easily skip this part so you end up setting it to true every loop. It would have been quite nice to have an 'else' condition that triggers when the generator is empty (which also fits quite nicely with all empty containers being considered falsy).
- kd5bjo 8y ago> However I'm struggling to find a use case for the python for-else definition where you don't end up doing something like 'result=something; break' anyway. What would be the point of breaking if you don't have any results? And if you have such a situation, wouldn't an exception make more sense? This is also useful for an accumulator and sentinel case. Say you're parsing a file and need to grab a null-terminated string: result = '' for b in file_bytes_iterator: if b == '\0': break result += b else: throw ValueError("String is unterminated") result will contain the parsed string, and file_bytes_iterator will be ready to return the first byte after the terminator, to continue parsing the file
- contravariant 8y agoFor what it's worth you could also write that as: result = '' for b in file_bytes_iterator: if b == '\0': break result += b if b != '\0': throw ValueError("String is unterminated") And while we're one the subject, I would also really like to have a construction like: result = '' while b != '\0' for b in file_bytes_iterator: result += b if b != '\0': throw ValueError("String is unterminated") but I fear opinion might be divided on that one.
- kd5bjo 8y agoIt's a syntax sugar feature, so its presence or absence will make little difference in the grand scheme of things -- there will always be a relatively easy way to rewrite code without it. Personally, I would prefer the loop iteration variable to only be in scope within the loop body, and generally write code as if that were true. Also, repeating the sentinel test is asking for a future edit to change one and miss the other.
- fyi1183 8y agoYour suggested replacement duplicates the break condition, which is not ideal for maintainability. Also, it only happens to work due to Python's variable scoping rules. I have wished for a for-else construct in C and C++ many times: having to broaden the scope of a loop iteration variable just to duplicate a loop break check really sucks.
- kd5bjo 8y agoAfter letting it steep overnight, I came up with this variant which addresses most of the issues that have come up in this thread: try: result = '' while (b = next(file_bytes_iterator)) != '\0': result += b # maybe parse more of the file here except StopIteration: throw ValueError("Unexpected end of file")