Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why can't I return self in this Swift indirect enum?

Why can’t I return self at the indicated point?

indirect enum BinarySearchTree<E: Comparable> {
    case leaf
    case node(BinarySearchTree<E>, E, BinarySearchTree<E>)

    mutating func insert(_ e: E) {
        switch self {
        case .leaf:
            self = .node(.leaf, e, .leaf)
        case .node(var left, let v, var right):
            if e < v { left.insert(e) }
            if e > v { right.insert(e) }
            self = .node(left, v, right)
            // Why can't I just return self here? e == v, so isn't it already a .node(left, v, right)?
        }
    }
}

When I run the following code, returning self

var bst = BinarySearchTree<Int>()
bst.insert(3)
bst.insert(5)

the program just stays at its initialization as

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

.node(leaf, 3, leaf)

Thank you!

>Solution :

The reason you need to use self = .node(left, v, right) is because at that point, self is equal to (.leaf, 3, .leaf). The local variable right has just been updated to (.leaf, 5, .leaf).

Updating the local variable right does not update self‘s right directly. So you need to finish off that case with self = .node(left, v, right) to update its right value (or its left value as the case may be).

You can confirm this by adding the following line after the two if statements:

print("After insert: self = \(self), right = \(right)")

This prints:

After insert: self = node(__lldb_expr_53.BinarySearchTree<Swift.Int>.leaf, 3, __lldb_expr_53.BinarySearchTree<Swift.Int>.leaf), right = node(__lldb_expr_53.BinarySearchTree<Swift.Int>.leaf, 5, __lldb_expr_53.BinarySearchTree<Swift.Int>.leaf)

As you can see, self‘s right has not been updated. Only the local variable right has been updated.

Here’s a more explicit version of the switch statement that may make it clearer:

switch self {
    case .leaf:
        self = .node(.leaf, e, .leaf)
    case .node(var left, let v, var right):
        if e < v {
            left.insert(e)
            self = .node(left, v, right)
        } else if e > v {
            right.insert(e)
            self = .node(left, v, right)
        }
}

You don’t need to do anything in when e == v, you only need to update self after updating either left or right.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading