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
.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.