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

Reply via email to