karan satia karan satia - 5 months ago 28
Swift Question

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.

Answer

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
}