I'm not really seeing the advantage of `for item in collection else` being discussed or a compelling use case that motivates a language change.
You can check the empty case first for empty collections: if collection.isEmpty { ... } else for item in collection { ... } If you're filtering while iterating, you can use an access counter, for what is surely an uncommon test, or better yet, filter first and use the leading isEmpty test: var access = 0 for item in collection where condition { access += 1 } if access == 0 { } It seems to me that the only reason the language should change would be to handle abnormal loop processing, such as a break, but then why not throw an error and embed the for-loop in a do-catch? And honestly, I don't really think I'd ever use this or could think of a scenario where I'd need this. -- E > On Feb 3, 2017, at 10:01 AM, Thorsten Seitz via swift-evolution > <swift-evolution@swift.org> wrote: > > I would prefer `ifNone:` instead of `otherwise` as it makes the semantics > clearer IMHO. > > -Thorsten > > Am 03.02.2017 um 12:50 schrieb Haravikk via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>: > >> >>> On 2 Feb 2017, at 13:44, Derrick Ho <wh1pch...@gmail.com >>> <mailto:wh1pch...@gmail.com>> wrote: >>> >>> Maybe we can add a new parameter "otherwise" to the forEach method >>> >>> [1,2,3,4].forEach({ >>> // do something >>> } >>> , otherwise: { >>> // do something if it is an empty array >>> }) >> >> That could be a decent compromise; just tried a simple extension and the >> following seems to work quite nicely: >> >> extension Sequence { >> func forEach(_ body: (Iterator.Element) throws -> Void, otherwise: () >> throws -> Void) rethrows -> Void { >> var it = self.makeIterator() >> if let first = it.next() { >> try body(first) >> while let current = it.next() { try body(current) } >> } else { try otherwise() } >> } >> } >> >> let names = ["foo", "bar", "baz"], empty:[String] = [] >> names.forEach({ print($0) }, otherwise: { print("no names") }) >> empty.forEach({ print($0) }, otherwise: { print("no names") }) >> >> Of course it lacks the ability to use continue or break, so the question is; >> does it add enough utility to add, or is it better left to developers to >> extend themselves? >> >>> On Thu, Feb 2, 2017 at 6:31 AM Haravikk via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> I'm of two minds on this feature; I kind of support the idea of the >>> construct, especially because there are some behind the scenes >>> optimisations it can do, and it can look neater. >>> However, I'm not at all keen on the re-use of else; if there were a better >>> keyword I might suppose that, for example "empty" or something like that, >>> but nothing I can think of feels quite right. >>> >>> I mean, when it comes down to it the "best" way to write the loop is like: >>> >>> var it = names.makeIterator() >>> if let first = it.next() { >>> print(first) >>> while let current = it.next() { print(current) } >>> } else { print("no names") } >>> >>> However this is a horrible thing to do in your own code, especially if the >>> loop body is larger than one line, but is just fine if it's done behind the >>> scenes for you (complete with unwrapping of the iterators if their type is >>> known). >>> >>> Which is why I kind of like the idea of having the construct itself; >>> otherwise, like others, I use the less "correct" option like so (for >>> sequences): >>> >>> var empty = true >>> for name in names { print(name); empty = false } >>> if empty { print("no names") } >>> >>> At which point I simply hope that the compiler optimises away the >>> assignment (since it only actually does something on the first pass). >>> >>> So yeah, I can see a use for it, but I'd prefer a construct other than >>> for/else to do it; at the very least a different keyword, as there's the >>> possibility we could also have a while/else as well and it would need to be >>> very clear, which I don't feel that for/else is. >>> >>>> On 2 Feb 2017, at 11:06, Jeremy Pereira via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>> >>>>> >>>>> On 1 Feb 2017, at 18:29, Chris Davis via swift-evolution >>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>>> >>>>> ah! I forgot about the break semantics, that’s definitely one for the con >>>>> list. >>>>> >>>>> I like Nicolas’ solution, clear to read. >>>>> >>>>>> On 1 Feb 2017, at 18:18, Nicolas Fezans <nicolas.fez...@gmail.com >>>>>> <mailto:nicolas.fez...@gmail.com>> wrote: >>>>>> >>>>>> I tend to write this kind of treatment the other way around... >>>>>> >>>>>> if names.isEmpty { >>>>>> // do whatever >>>>>> } // on other cases I might have a few else-if to treat other cases that >>>>>> need special treament >>>>>> else { >>>>>> for name in names { >>>>>> // do your thing >>>>>> } >>>>>> } >>>>>> >>>> >>>> >>>> This only works if you know the size of the sequence before you start >>>> iterating it. You can, for example, iterate a lazy sequence and >>>> calculating its size before iterating it defeats the object.Thus for { … } >>>> else { … } where the else block only executes if the for block was never >>>> executed does have some utility. >>>> >>>> However, I am not in favour adding it. The same functionality can be >>>> achieved by counting the number of iterations and testing the count >>>> afterwards (or by using a boolean). It takes a couple of extra lines of >>>> code and an extra variable, but I think that is a Good Thing. It’s more >>>> explicit and (as the Python example shows) there could be hidden >>>> subtleties that confuse people if for … else … is badly designed. Also, in >>>> many cases, I would argue that treating the zero element sequence >>>> differently to the n > 0 element sequence is a code smell. About the only >>>> use-case I can think of off the top of my head is UI presentation e.g. >>>> “your search didn’t return any results” instead of a blank page. >>>> >>>> Talking of Python, Swift is not Python and the argument not to implement a >>>> feature because its semantics conflict with the semantics of a similar >>>> looking feature in another language is bogus. I don’t see the Python for … >>>> else being different (and having looked it up to see what you all were >>>> talking about, my opinion is that the Python for … else is a disaster) as >>>> being a legitimate con to this cleaner and more logical idea in Swift. >>>> >>>>>> >>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution> > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution