Last active
March 5, 2017 13:20
-
-
Save airspeedswift/71f15d1eb866be9e5ac7 to your computer and use it in GitHub Desktop.
Swift copy-on-write behaviour for a struct using HeapBuffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ideally we would define this inside the tree struct | |
private class _Node<T: Comparable> { | |
var _value: T | |
var _left: _Node<T>? = nil | |
var _right: _Node<T>? = nil | |
init(value: T) { _value = value } | |
} | |
public struct Tree<T: Comparable> { | |
// this makes things a bit more pleasant later | |
private typealias Node = _Node<T> | |
private var _root: Node? = nil | |
public init() { } | |
// constructor from a sequence | |
public init<S: SequenceType where S.Generator.Element == T>(_ seq: S) { | |
var g = seq.generate() | |
while let x: T = g.next() { | |
self.insert(x) | |
} | |
} | |
// check root node to see if the Tree's been copied, | |
// and if it has, replicate itself... | |
private mutating func ensureUnique() { | |
if !isUniquelyReferencedNonObjC(&_root) { | |
println("copying myself") | |
// inefficiently... | |
self = Tree<T>(self) | |
} | |
} | |
public mutating func insert(value: T) { | |
ensureUnique() | |
_root = insert(_root, value) | |
} | |
private mutating func insert(node: Node?, _ value: T) -> Node? { | |
switch node { | |
case .None: | |
return Node(value: value) | |
case let .Some(node) where value < node._value: | |
node._left = insert(node._left, value) | |
return node | |
case let .Some(node): | |
node._right = insert(node._right, value) | |
return node | |
} | |
} | |
public func contains(value: T) -> Bool { | |
return contains(_root, value) | |
} | |
private func contains(node: Node?, _ value: T) -> Bool { | |
switch node { | |
case .None: | |
return false | |
case let .Some(node) where node._value == value: | |
return true | |
case let .Some(node): | |
return contains( | |
value < node._value | |
? node._left : node._right, | |
value) | |
} | |
} | |
} | |
extension Tree: SequenceType { | |
typealias Generator = GeneratorOf<T> | |
public func generate() -> Generator { | |
var stack: [Node] = [] | |
var current: Node? = _root | |
return GeneratorOf { | |
// stack-based technique for inorder traversal | |
// without recursion | |
while true { | |
if let node = current { | |
stack.append(node) | |
current = node._left | |
} | |
else if !stack.isEmpty { | |
let pop = stack.removeLast() | |
current = pop._right | |
return pop._value | |
} | |
else { | |
return nil | |
} | |
} | |
} | |
} | |
} | |
extension Tree: Printable { | |
public var description: String { | |
return "[" + ", ".join(lazy(self).map(toString)) + "]" | |
} | |
} | |
var tree = Tree<String>() | |
tree.insert("Emily") | |
tree.insert("Thomas") | |
var tree2 = tree | |
println("Copied tree2") | |
println("Now changing tree") | |
tree.insert("Gordon") | |
tree.insert("James") | |
tree.insert("James") | |
tree.insert("Henry") | |
tree.contains("Thomas") | |
tree.contains("Gordon") | |
tree.contains("Henry") | |
tree.contains("James") | |
tree.contains("Spencer") | |
tree.contains("Gordon") | |
tree2.contains("Gordon") | |
var tree3 = tree2 | |
println("Now changing tree3") | |
tree3.insert("The Fat Controler") | |
println(tree) | |
println(tree2) | |
println(tree3) | |
isUniquelyReferencedNonObjC(&tree._root) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment