For... else


(Lee M) #1

This has likely been discussed already, but I haven't been able to find it
anywhere.
Example:

    let items: Int = []

    for item in items {
        print(item)
    }
    else {
        print("No items")
    }


(Ben Langmuir) #2

Previous discussion here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

···

On Jan 22, 2016, at 8:22 AM, Lee M via swift-evolution <swift-evolution@swift.org> wrote:

This has likely been discussed already, but I haven't been able to find it anywhere.
Example:

    let items: Int = []

    for item in items {
        print(item)
    }
    else {
        print("No items")
    }
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Félix Cloutier) #3

I frequently need something like that and I'd like to have it in Swift too.

Félix

···

Le 22 janv. 2016 à 13:22:45, Ben Langmuir via swift-evolution <swift-evolution@swift.org> a écrit :

Previous discussion here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

On Jan 22, 2016, at 8:22 AM, Lee M via swift-evolution <swift-evolution@swift.org> wrote:

This has likely been discussed already, but I haven't been able to find it anywhere.
Example:

   let items: Int = []

   for item in items {
       print(item)
   }
   else {
       print("No items")
   }
_______________________________________________
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


(Howard Lovatt) #4

It would be easy enough to add:

func forEach(
    @noescape elements body: (Element) throws -> Void,
    @noescape otherwise otherwise: () throws -> Void
) rethrows

to the standard library or write it yourself.

···

On 23 Jan 2016, at 12:59 PM, Félix Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

I frequently need something like that and I'd like to have it in Swift too.

Félix

Le 22 janv. 2016 à 13:22:45, Ben Langmuir via swift-evolution <swift-evolution@swift.org> a écrit :

Previous discussion here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

On Jan 22, 2016, at 8:22 AM, Lee M via swift-evolution <swift-evolution@swift.org> wrote:

This has likely been discussed already, but I haven't been able to find it anywhere.
Example:

   let items: Int = []

   for item in items {
       print(item)
   }
   else {
       print("No items")
   }
_______________________________________________
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Matthew Johnson) #5

It would be easy enough to add:

func forEach(
    @noescape elements body: (Element) throws -> Void,
    @noescape otherwise otherwise: () throws -> Void
) rethrows

to the standard library or write it yourself.

Not unless / until we get the ability for a noescape closure to influence control flow (break, return, etc). Even then this is clunkier than adding else to the language would be.

···

Sent from my iPad

On Jan 25, 2016, at 3:41 AM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

On 23 Jan 2016, at 12:59 PM, Félix Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

I frequently need something like that and I'd like to have it in Swift too.

Félix

Le 22 janv. 2016 à 13:22:45, Ben Langmuir via swift-evolution <swift-evolution@swift.org> a écrit :

Previous discussion here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

On Jan 22, 2016, at 8:22 AM, Lee M via swift-evolution <swift-evolution@swift.org> wrote:

This has likely been discussed already, but I haven't been able to find it anywhere.
Example:

   let items: Int = []

   for item in items {
       print(item)
   }
   else {
       print("No items")
   }
_______________________________________________
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

_______________________________________________
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


(Andrew Bennett) #6

This may do what you want:

    let values: [Int] = [1,2,3,4]

    if let sequence = nonEmptySequence(values) {

        for element in sequence {

            print("element: \(element)")

        }

    }

    else {

        print("empty!")

    }

It's also more flexible, you can do work after the for loop (that work
won't execute in the else), you can also use PeekSequence directly to get
the first value. This is handy for something like an average (reduce) where
you don't necessarily have a zero value.

The implementation can be found here:
https://github.com/therealbnut/PeekSequence

···

On Tue, Jan 26, 2016 at 12:59 AM, Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

Sent from my iPad

On Jan 25, 2016, at 3:41 AM, Howard Lovatt via swift-evolution < > swift-evolution@swift.org> wrote:

It would be easy enough to add:

   - func forEach(
   - @noescape elements body: (Element) throws -> Void,
   - @noescape otherwise otherwise: () throws -> Void
   - ) rethrows

to the standard library or write it yourself.

Not unless / until we get the ability for a noescape closure to influence
control flow (break, return, etc). Even then this is clunkier than adding
else to the language would be.

On 23 Jan 2016, at 12:59 PM, Félix Cloutier via swift-evolution < > swift-evolution@swift.org> wrote:

I frequently need something like that and I'd like to have it in Swift too.

Félix

Le 22 janv. 2016 à 13:22:45, Ben Langmuir via swift-evolution < > swift-evolution@swift.org> a écrit :

Previous discussion here:

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

On Jan 22, 2016, at 8:22 AM, Lee M via swift-evolution < > swift-evolution@swift.org> wrote:

This has likely been discussed already, but I haven't been able to find it
anywhere.
Example:

   let items: Int = []

   for item in items {
       print(item)
   }
   else {
       print("No items")
   }
_______________________________________________
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

_______________________________________________
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Félix Cloutier) #7

This is more a demonstration that the for...else construct isn't obvious than a solution to the problem. In Python, the else branch of a for loop is executed when you went through all the iterations without breaking ("when the loop condition becomes false", which doesn't happen if you break from the loop).

Félix

···

Le 25 janv. 2016 à 23:14:23, Andrew Bennett via swift-evolution <swift-evolution@swift.org> a écrit :

This may do what you want:

    let values: [Int] = [1,2,3,4]
    if let sequence = nonEmptySequence(values) {
        for element in sequence {
            print("element: \(element)")
        }
    }
    else {
        print("empty!")
    }

It's also more flexible, you can do work after the for loop (that work won't execute in the else), you can also use PeekSequence directly to get the first value. This is handy for something like an average (reduce) where you don't necessarily have a zero value.

The implementation can be found here: https://github.com/therealbnut/PeekSequence

On Tue, Jan 26, 2016 at 12:59 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Sent from my iPad

On Jan 25, 2016, at 3:41 AM, Howard Lovatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It would be easy enough to add:

func forEach(
    @noescape elements body: (Element) throws -> Void,
    @noescape otherwise otherwise: () throws -> Void
) rethrows

to the standard library or write it yourself.

Not unless / until we get the ability for a noescape closure to influence control flow (break, return, etc). Even then this is clunkier than adding else to the language would be.

On 23 Jan 2016, at 12:59 PM, Félix Cloutier via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I frequently need something like that and I'd like to have it in Swift too.

Félix

Le 22 janv. 2016 à 13:22:45, Ben Langmuir via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Previous discussion here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

On Jan 22, 2016, at 8:22 AM, Lee M via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This has likely been discussed already, but I haven't been able to find it anywhere.
Example:

   let items: Int = []

   for item in items {
       print(item)
   }
   else {
       print("No items")
   }
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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


(Andrew Bennett) #8

What you described Felix seems to be different to what was proposed, also I
think (as you suggest) that `else` is unclear for what you describe.

To clarify, is what you're suggesting logically equivalent to this?

if let found = [1,2,3,4].find({ $0 == 3 }) {

    print("exited early (\(found))")

}

extension SequenceType {

    func find(

        @noescape each: Generator.Element throws -> Bool

    ) rethrows -> Generator.Element? {

        for element in self {

            if try each(element) == false {

                return element

            }

        }

        return nil

    }

}

If that's correct then I prefer the keyword in the other thread `nobreak`
although it could be a better.

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

We'd have to confirm with Lee, but their example (this thread) seems
oriented around zero items rather than early exit:

let items: Int = []

for item in items {

    print(item)

}

else {

    print("No items")

}

My suggestion works for zero items.

···

On Wed, Jan 27, 2016 at 4:47 AM, Félix Cloutier <felixcca@yahoo.ca> wrote:

This is more a demonstration that the for...else construct isn't obvious
than a solution to the problem. In Python, the else branch of a for loop is
executed when you went through all the iterations without breaking ("when
the loop condition becomes false", which doesn't happen if you break from
the loop).

Félix

Le 25 janv. 2016 à 23:14:23, Andrew Bennett via swift-evolution < > swift-evolution@swift.org> a écrit :

This may do what you want:

    let values: [Int] = [1,2,3,4]
    if let sequence = nonEmptySequence(values) {
        for element in sequence {
            print("element: \(element)")
        }
    }
    else {
        print("empty!")

    }

It's also more flexible, you can do work after the for loop (that work
won't execute in the else), you can also use PeekSequence directly to get
the first value. This is handy for something like an average (reduce) where
you don't necessarily have a zero value.

The implementation can be found here:
https://github.com/therealbnut/PeekSequence

On Tue, Jan 26, 2016 at 12:59 AM, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:

Sent from my iPad

On Jan 25, 2016, at 3:41 AM, Howard Lovatt via swift-evolution < >> swift-evolution@swift.org> wrote:

It would be easy enough to add:

   - func forEach(
   - @noescape elements body: (Element) throws -> Void,
   - @noescape otherwise otherwise: () throws -> Void
   - ) rethrows

to the standard library or write it yourself.

Not unless / until we get the ability for a noescape closure to influence
control flow (break, return, etc). Even then this is clunkier than adding
else to the language would be.

On 23 Jan 2016, at 12:59 PM, Félix Cloutier via swift-evolution < >> swift-evolution@swift.org> wrote:

I frequently need something like that and I'd like to have it in Swift
too.

Félix

Le 22 janv. 2016 à 13:22:45, Ben Langmuir via swift-evolution < >> swift-evolution@swift.org> a écrit :

Previous discussion here:

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

On Jan 22, 2016, at 8:22 AM, Lee M via swift-evolution < >> swift-evolution@swift.org> wrote:

This has likely been discussed already, but I haven't been able to find
it anywhere.
Example:

   let items: Int = []

   for item in items {
       print(item)
   }
   else {
       print("No items")
   }
_______________________________________________
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

_______________________________________________
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

_______________________________________________
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


(Félix Cloutier) #9

You are right. Someone else overly eagerly linked this other thread <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html> and brought me into their confusion :slight_smile:

Félix

···

Le 26 janv. 2016 à 17:30:58, Andrew Bennett <cacoyi@gmail.com> a écrit :

What you described Felix seems to be different to what was proposed, also I think (as you suggest) that `else` is unclear for what you describe.

To clarify, is what you're suggesting logically equivalent to this?

if let found = [1,2,3,4].find({ $0 == 3 }) {
    print("exited early (\(found))")
}

extension SequenceType {
    func find(
        @noescape each: Generator.Element throws -> Bool
    ) rethrows -> Generator.Element? {
        for element in self {
            if try each(element) == false {
                return element
            }
        }
        return nil
    }
}

If that's correct then I prefer the keyword in the other thread `nobreak` although it could be a better.

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

We'd have to confirm with Lee, but their example (this thread) seems oriented around zero items rather than early exit:

let items: Int = []

for item in items {
    print(item)
}
else {
    print("No items")
}

My suggestion works for zero items.

On Wed, Jan 27, 2016 at 4:47 AM, Félix Cloutier <felixcca@yahoo.ca <mailto:felixcca@yahoo.ca>> wrote:
This is more a demonstration that the for...else construct isn't obvious than a solution to the problem. In Python, the else branch of a for loop is executed when you went through all the iterations without breaking ("when the loop condition becomes false", which doesn't happen if you break from the loop).

Félix

Le 25 janv. 2016 à 23:14:23, Andrew Bennett via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

This may do what you want:

    let values: [Int] = [1,2,3,4]
    if let sequence = nonEmptySequence(values) {
        for element in sequence {
            print("element: \(element)")
        }
    }
    else {
        print("empty!")
    }

It's also more flexible, you can do work after the for loop (that work won't execute in the else), you can also use PeekSequence directly to get the first value. This is handy for something like an average (reduce) where you don't necessarily have a zero value.

The implementation can be found here: https://github.com/therealbnut/PeekSequence

On Tue, Jan 26, 2016 at 12:59 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Sent from my iPad

On Jan 25, 2016, at 3:41 AM, Howard Lovatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It would be easy enough to add:

func forEach(
    @noescape elements body: (Element) throws -> Void,
    @noescape otherwise otherwise: () throws -> Void
) rethrows

to the standard library or write it yourself.

Not unless / until we get the ability for a noescape closure to influence control flow (break, return, etc). Even then this is clunkier than adding else to the language would be.

On 23 Jan 2016, at 12:59 PM, Félix Cloutier via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I frequently need something like that and I'd like to have it in Swift too.

Félix

Le 22 janv. 2016 à 13:22:45, Ben Langmuir via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Previous discussion here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001110.html

On Jan 22, 2016, at 8:22 AM, Lee M via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This has likely been discussed already, but I haven't been able to find it anywhere.
Example:

   let items: Int = []

   for item in items {
       print(item)
   }
   else {
       print("No items")
   }
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
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