iGodric iGodric - 1 month ago 14
Swift Question

Jump out of deeply recursive function call

I wrote a parser in Objective-C about a highly ambiguous language. Everything works fine. I often jump out of many function calls with throwing an exception (I keep being in my code, so the exception will never get out of the parser).

I thought of porting the code to Swift, then I noticed that there is no exception handling in Swift.

I don't want exception handling nor do I need it, but the jumping out of many different nested  function calls came in handy while writing parsers.

Is there a good way instead of the jump of exceptions to the

@catch
block in Swift?




Example of recursive function, to make it more clear (working playground code):

import Foundation

func addToSum(sum: Int, rest: String) -> Int {
if rest == "" {
return sum
} else {
if rest[rest.endIndex.predecessor()] != "i" {
// can't throw exception, if scratches is like "iiiiiiiiiiiioiiiiii"
}

var shorterRest = rest.substringToIndex(rest.endIndex.predecessor())
return addToSum(sum + 1, shorterRest)
}
}

let scratches = "iiiiiiiiiiiiiiiiiiiii"
var sum = addToSum(0, scratches) // sum is 11 ;-)


I know the example isn't that good because it is only one function and you could easily add an error, but then I had to go every function call back.

Please see the bigger picture. I don't need backtracing in the parser.




Here is a link that has the same problem: Use exceptions as flow control in parsers. Unfortunately it doesn't give an answer.

Answer

This is handled pretty easily in this case by returning an Optional. Instead of throwing an exception, just return nil and let it propagate back up the chain.

func addToSum(sum: Int, rest: String) -> Int? {
    if rest == "" {
        return sum
    } else {
        if rest[rest.endIndex.predecessor()] != "i" {
            return nil
        }

        var shorterRest = rest.substringToIndex(rest.endIndex.predecessor())
        return addToSum(sum + 1, shorterRest)
    }
}

let scratches = "iiiiiiiiiiiiiiiiiiiii"
var sum = addToSum(0, scratches)  // sum is 21, actually
sum = addToSum(0, "iiiioiii")     // sum is now nil
Comments