0

https://nearthespeedoflight.com/browser.html

    func untilThrowOrEndOfTokensReached<ConsumedType>(perform: () throws -> ConsumedType) -> [ConsumedType] {

    var results = [ConsumedType]()

    do {
        while isNotAtEnd {
            results.append(try perform())
        }
    } catch {
        return results
    }
    return results
}

Double return results looks strange and I want to fix it.

There is a similar question:

What's the equivalent of finally in Swift

It is recommended to use defer but this code won't work:

func untilThrowOrEndOfTokensReached<ConsumedType>(perform: () throws -> ConsumedType) -> [ConsumedType] {
    
    var results = [ConsumedType]()
    defer {
        return results
    }
    do {
        while isNotAtEnd {
            results.append(try perform())
        }
    } catch {
    }
}

'return' cannot transfer control out of a defer statement

How to resolve this issue? Or should I just remove return results inside catch block?

Cheolhyun
  • 169
  • 1
  • 7
Gargo
  • 1,135
  • 1
  • 10
  • 21
  • 1
    Add `return 0` as the last line? It kind of depends what the aim of the function is. – Joakim Danielson Apr 23 '23 at 19:05
  • What are you trying you achieve? As it stands it's not cleart in this sample code - you have a `try...catch` block that doesn't appear to be doing useful work, as whatever you are doing is then ignored and `0` returned. You could just return `0`. – flanker Apr 23 '23 at 19:06
  • 1
    Also note that if it’s Java `finally` you are referring to then you can’t call `return` in Java either which kind of make your question even more unclear – Joakim Danielson Apr 23 '23 at 19:21
  • To be more explicit on what the issue is here: that `defer` block runs _after_ the function body has already done its `return`. – Alexander Apr 23 '23 at 19:44
  • a lot of people ask for addtional info. So I posted a detailed description. – Gargo Apr 23 '23 at 19:56
  • Since you are ignoring the error you can do `try? results.append(perform())` followed by a single `return` statement. – Joakim Danielson Apr 23 '23 at 20:05

1 Answers1

0

You don't need a defer here at all. I think what you're looking for is:

func untilThrowOrEndOfTokensReached<ConsumedType>(perform: () throws -> ConsumedType) -> [ConsumedType] {
    var results = [ConsumedType]()

    do {
        while isNotAtEnd {
            results.append(try perform())
        }
    } catch {
        // Log the error or whatever
    }

    return results
}

This will return the results accumulate so far, as soon as the first perform() call raises.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • it won't compile because `return results` is inside `catch` block and may not be executed – Gargo Apr 24 '23 at 10:51