swiftlinked-listswift2switch-statementguard-statement

Misuse of guard statement to replace nil checking


I'm doing something really simple just to get used to Swift (coming from objc) - I want to return a desired node in a linked list by using a guard statement and a switch statement. I'm obviously misusing the guard statement because my else clause is huge (it's where my switch statement is being kept). Perhaps I don't even need a switch statement, but it just cleans things up a bit.

My old code is as follows:

func getValue (atIndex index: Int) -> T {
    if count < index || index < 0 {
        print ("index is outside of possible range")
    }
    var root = self.head
    //        if var root = self.head {
    if index == 0 {
        return (self.head?.value)!
    }
    if index == count-1 {
        return (self.tail?.value)!
    }
    else {
        for _ in 0...index-1 {
            root = root!.next!
        }
    }
    return root!.value
}

Replaced with a guard statement (but getting a compiler error that the guard body may not fall through) - my problem is what to return, since my function return type is <T> (any type).

func getValue (atIndex index: Int) -> T {
    guard  (count < index || index < 0) else {
        switch true {
        case index == 0:
            if let head = self.head {
                return head.value
            }
        case index == count-1:
            if let tail = self.tail {
                return tail.value
            }
        default:
            if var currentNode = head {
                for _ in 0...index-1 {
                    currentNode = currentNode.next!
                }
                return currentNode.value
            }
        }
    }
}

I'd like to add a print statement outside of my guard statement saying that the desired index is outside of the range, but I also need to return something at the end of the function of type T. The problem is that outside of my guard and switch statement, I have nothing to return.


Solution

  • The guard statement is used to catch the invalid case, so you'd want something like:

    func getValueAtIndex(index: Int) -> T {
        guard index >= 0 && index < count else {
            // Invalid case
            print("Index is outside of possible range")
    
            // Guard must return control or call a noreturn function.
            // A better choice than the call to fatalError might be
            // to change the function to allow for throwing an exception or returning nil.
            fatalError("Index out of bounds")
        }
    
        // Valid cases
    }