> 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