> On 2 Feb 2017, at 13:44, Derrick Ho <[email protected]> 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 
> <[email protected] <mailto:[email protected]>> 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 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>>> 
>>> On 1 Feb 2017, at 18:29, Chris Davis via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> 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 <[email protected] 
>>>> <mailto:[email protected]>> 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
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> _______________________________________________
> swift-evolution mailing list
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to