Guard in Swift giving different answer to if

Viewed 60

In a very simple program to compare two linked lists, I have a recursive function that tests if the current node of both lists are the same, and then move to the next node.

The base case is if the two nodes are nil, we exit.

So the code with if / else

is:

func compareLL(llistOne: SinglyLinkedListNode?, llistTwo: SinglyLinkedListNode?) -> Bool {
    if (llistOne == nil && llistTwo == nil) { return true }
    if (llistOne?.data == llistTwo?.data) {return compareLL(llistOne: llistOne?.next, llistTwo: llistTwo?.next)}
    return false
}

with guard

func compareLL(llistOne: SinglyLinkedListNode?, llistTwo: SinglyLinkedListNode?) -> Bool {
    guard (llistOne != nil && llistTwo != nil) else {return true}
    if (llistOne?.data == llistTwo?.data) {return compareLL(llistOne: llistOne?.next, llistTwo: llistTwo?.next)}
    return false
}

So why do they produce different results?

That is, comparing two different linked lists (different lengths) - so we return true when llistOne = 5 and list 2 = nil according to the guard statement (and this does not apply to the if then else statement). This is unexpected, as I thought they should obtain the same result.

How can I develop a guard statement to produce the same as the if pattern?

1 Answers

The negation of llistOne == nil && llistTwo == nil is llistOne != nil || llistTwo != nil.

Your if returns only if both values are nil. But your guard currently returns if either or both are nil. That's not the same.

So change your guard to:

guard (llistOne != nil || llistTwo != nil) else {return true}

You may wish to read up on De Morgan's Laws.

The basic summary De Morgan's Laws for boolean logic is:

not(a and b) === not(a) or not(b)
not(a or b) === not(a) and not(b)

In your case, a is llistOne == nil while b is llistTwo == nil.

You had a and b (llistOne == nil && llistTwo == nil). So not(a and b) is not(a) or not(b) (llistOne != nil || llistTwo != nil)

Related