Search code examples
c#swiftguard

Swift do-return with guard condition?


I'm trying to translate some Swift code to C#. I read the docs, but am not able to grasp what this code block does. I'm not able to run the code, so that makes it even harder. Please help!

do {
    oldArray.enumerated().forEach { oldTuple in
        guard case .entry = oldTuple.element else {
            return
        }

        // Do stuff
    }
}
  1. Is this return equivalent to a break?
  2. What is the guard condition? Some assignment...?

Solution

  • Swift playgrounds are a great place to explore the language. Even though you can't run the whole code, you can put a few support pieces around it to see what is happening.

    oldArray clearly holds some enum values. From your snippet, we can see that one of the values is .entry. I've created an enum called State for exploration purposes and given it a few cases (entry, foo, bar).

    Now throw your snippet into a function and give it an oldArray to work with. Add a print in the // Do stuff section and the truth will be revealed:

    enum State {
        case entry
        case foo
        case bar
    }
    
    func test() {
        let oldArray: [State] = [.entry, .entry, .bar, .entry, .foo]
    
        do {
            oldArray.enumerated().forEach { oldTuple in
                guard case .entry = oldTuple.element else {
                    return
                }
    
                // Do stuff
                print(oldTuple)
            }
        }
    }
    
    test()
    

    Output

    (offset: 0, element: __lldb_expr_1.State.entry)
    (offset: 1, element: __lldb_expr_1.State.entry)
    (offset: 3, element: __lldb_expr_1.State.entry)
    

    Is this return equivalent to a break?

    It returns from the closure if the guard condition isn't met.

    What is the guard condition? Some assignment...?

    .enumerated turns oldArray into a sequence of (offset: Int, element: State) tuples. So the example array becomes [(offset: 0, element: .entry), (offset: 1, element: .entry), ...]. forEach takes each of those tuples in turn and assigns it to oldTuple.

    The guard is using pattern matching to verify that the current tuple's element value is .entry otherwise it exits the closure.

    The syntax is a bit odd, but it is saying, to continue beyond this statement, the current tuple's element must be a .entry otherwise return from the closure and abandon processing this element.

    So, this code loops through an array of enums and processes only the ones that are .entry.

    What does the do do?

    Nothing that we can see from your snippet. If you comment out do { and the corresponding } the test still does the same thing. do is usually used with Error handing to surround calls that might throw an error. do statements are usually used with catch statements which then catch the thrown error. By itself, do { } just creates a new scope.