Swift Recursion/ Class constructors - swift

I am writing a Swift program that will solve post script equations. I have two Classes: ExpressionTree, and ExpressionTreeLeaf, which inherits Expression Tree. In the ExpressionTree Class, I need a method that solves the tree. I also need to override that function in the ExpressionTreeLeaf Class to just return the data of the leaf. I'll give some code for context:
ExpressionTree class:
class ExpressionTree{
let Left: ExpressionTree?
let Right: ExpressionTree?
let Data: String
// constructor for tree with known left and right
init(Data: String, Left: ExpressionTree? = nil, Right: ExpressionTree? = nil) {
self.Data = Data
self.Left = Left
self.Right = Right
}
// constructor for tree with only data
init(Data:String){
self.Data = Data
self.Left = nil
self.Right = nil
}
// this method returns double regardless of inputs
func ApplyOp(val1: Double, val2: Double, op:String) -> Double?{
switch op {
case "+":
return val1 + val2
case "-":
return val1 - val2
case "*":
return val1 * val2
case "/":
if( val2 != 0 ){
return val1 / val2
}
else{
return nil
}
default:
return nil
}
}
func Solve() -> Double{
return ApplyOp(val1: (Left?.Solve())!, val2: (Right?.Solve())!, op: Data)!
}
ExpressionTreeLeaf Class:
class ExpressionTreeLeaf: ExpressionTree {
init(_ Data: String) {
super.init(Data: "\(Data)")
}
func Solve() -> String {
return Data
}
}
My question is this: While using the debugger, I never seem to go into the ExpressionTreeLeaf constructor. I recursively go into the same solve method, and get error because the parameters are in the wrong place, causing them to be defaulted to 0.0. How to I get the recursive call to go into the ExpressionTreeLeaf class, so that when called, it will return the data of the leaf?
Thank you
EDIT:
here is the method to make the Tree:
expression is in postfix notation
func MakeTree(expression: [String]) -> ExpressionTree{
let precedance: [String: Int] = ["+": 1 , "-": 1, "*": 2, "/": 2]
var stack: Deque<ExpressionTree> = []
for piece in expression {
if(isNumber(check: "\(piece)")){
let tree: ExpressionTreeLeaf = ExpressionTreeLeaf("\(piece)")
stack.append(tree)
}
else if precedance["\(piece)"] != nil{
let tree1: ExpressionTree = stack.removeLast()
let tree2: ExpressionTree = stack.removeLast()
let newTree: ExpressionTree = ExpressionTree(Data: "\(piece)", Left: tree1, Right: tree2)
stack.append(newTree)
}
}
return stack.removeLast()
}

I realize you solved your problem but I would suggest using protocols rather than inheritance. Also, in Swift, value types such as enums and structs are preferred over classes.
First, here are a couple of utils for parsing the expression:
extension String {
var isDigits: Bool {
onlyConsistsOf(charactersIn: .decimalDigits)
}
var isMathOperation: Bool {
onlyConsistsOf(charactersIn: .init(charactersIn: "+-*/"))
}
func onlyConsistsOf(charactersIn set: CharacterSet) -> Bool {
rangeOfCharacter(from: set.inverted) == nil
}
}
extension Character {
var isDigit: Bool {
String(self).isDigits
}
var isMathOperation: Bool {
String(self).isMathOperation
}
}
Now we can get down to the nitty gritty. Let's start with a protocol:
protocol Evaluatable {
func evaluate() -> Double
}
Wether we are dealing with a an operation or an operand we can treat the types the same with protocol conformance. Notice how the Operand and Operation only store properties that they need. In your implementation your ExpressionTreeLeaf inherited from ExpressionTree even though it didn't need the Left or Right properties.
struct Operand: Evaluatable {
let value: Double
func evaluate() -> Double {
value
}
}
struct Operation: Evaluatable {
let lhs: Evaluatable
let rhs: Evaluatable
let op: Character
private var operation: (Double, Double) -> Double {
switch op {
case "+":
return (+)
case "-":
return (-)
case "*":
return (*)
case "/":
return (/)
default:
fatalError("Bad op: \(op)")
}
}
func evaluate() -> Double {
operation(lhs.evaluate(), rhs.evaluate())
}
}
Now let's create a top-level Tree type to store the root component to be evaluated. If you like, you can even make Tree conform to Evaluatable.
struct Tree: Evaluatable {
let root: Evaluatable
func evaluate() -> Double {
root.evaluate()
}
}
This factory method constructs the Tree using the same stack-based algorithm you posted. The stack is declared using the protocol we defined so we can store Operations or Operands.
enum TreeFactory {
static func makeTree(fromExpression expression: String) -> Evaluatable {
var stack: [Evaluatable] = []
for symbol in expression {
if symbol.isDigit {
stack.append(Operand(value: Double(String(symbol)) ?? 0.0))
} else if symbol.isMathOperation {
let rhs = stack.removeLast()
let lhs = stack.removeLast()
stack.append(Operation(lhs: lhs, rhs: rhs, op: symbol))
} else {
stack.removeAll()
break
}
}
return Tree(root: stack.isEmpty ? Operand(value: .zero) : stack.removeLast())
}
}
Let's conform to CustomStringConvertible for debugging purposes:
extension Operand: CustomStringConvertible {
var description: String { "\(value)" }
}
extension Operation: CustomStringConvertible {
var description: String { "(\(lhs) \(op) \(rhs))" }
}
extension Tree: CustomStringConvertible {
var description: String { "Tree: \(root) = \(evaluate())" }
}
Let's try this out:
let expression = "32+32+*3*2+1-2/"
let tree = TreeFactory.makeTree(fromExpression: expression)
print(tree)
Which results in:
Tree: ((((((3.0 + 2.0) * (3.0 + 2.0)) * 3.0) + 2.0) - 1.0) / 2.0) = 38.0
This problem can also be solved using an enum rather than with structs. Here's an alternate solution.
indirect enum TreeNode: Evaluatable {
case operand(Double)
case operation(Character, TreeNode, TreeNode)
case root(TreeNode)
func evaluate() -> Double {
switch self {
case .operand(let value):
return value
case .operation(let op, let lhs, let rhs):
switch op {
case "+":
return lhs.evaluate() + rhs.evaluate()
case "-":
return lhs.evaluate() - rhs.evaluate()
case "*":
return lhs.evaluate() * rhs.evaluate()
case "/":
return lhs.evaluate() / rhs.evaluate()
default:
return .zero
}
case .root(let node):
return node.evaluate()
}
}
}
Let's make another factory method to create an enum-based tree:
extension TreeFactory {
static func makeNodeTree(fromExpression expression: String) -> Evaluatable {
var stack: [TreeNode] = []
for symbol in expression {
if symbol.isDigit {
stack.append(.operand(Double(String(symbol)) ?? 0.0))
} else if symbol.isMathOperation {
let rhs = stack.removeLast()
let lhs = stack.removeLast()
stack.append(.operation(symbol, lhs, rhs))
} else {
stack.removeAll()
break
}
}
return TreeNode.root(stack.isEmpty ? .operand(.zero) : stack.removeLast())
}
}
Let's make our TreeNode debug friendly:
extension TreeNode: CustomStringConvertible {
var description: String {
switch self {
case .operand(let value):
return "\(value)"
case .operation(let op, let lhs, let rhs):
return "(\(lhs) \(op) \(rhs))"
case .root(let node):
return "Tree: \(node) = \(evaluate())"
}
}
}
And now to test it out:
let expression = "32+32+*3*2+1-2/"
let nodeTree = TreeFactory.makeNodeTree(fromExpression: expression)
print(nodeTree)
Here are the results:
Tree: ((((((3.0 + 2.0) * (3.0 + 2.0)) * 3.0) + 2.0) - 1.0) / 2.0) = 38.0

The problem is solved. I originally had incorrect return types which was not allowing me to call functions properly.

Related

Storing Generic Objects in a Heterogeneous Array and retrieving object parameter as the correct type

Ahoy everyone,
I have recently been trying to implement a Node based graph system that passes data between nodes using plugs. Similar to many of the 3D applications like houdini and maya.
I have written a similar system before using Python, and wanted to try this with Swift as my first learning excersise. Boy did I jump into the deep end on this one.
I am stuck now with Swifts Arrays, as I would like to store a list of Generic plugs.
Each plug can have its own value type float, int, color, string, Vector Matrix.
I have read up about Type Erasers and opaque types, but still cant seem to get my values our of a list in a way that I can perform some arithmetic on them.
All and any help that might put me in the direction would be greatly appreciated :D
import Foundation
import MetalKit
protocol genericPlug {
associatedtype T
func GetValue() -> T
}
class Plug<T>:genericPlug{
var _value:T?
var value:T {
get{GetValue()}
set(val){
value = val
}
}
func GetValue() -> T{
return _value!
}
init(_ newValue:T){
_value=newValue
}
}
class Node{
var plugs:[genericPlug] = []
init(){
var p1 = Plug<Int>(0)
var p2 = Plug(vector2(1.2, 3.1))
var p3 = Plug([0.0, 3.1, 0.6, 1])
plugs.append(p1)
plugs.append(p2)
plugs.append(p3)
}
func execute(){
// will access the plugs in the array and perform some sort of calculations on them.
plugs[0].value + 1 // should equal 1
plugs[1].value.x + 0.8 // should have x=2.0 y=3.1
plugs[2].value[1] - 0.1 // should equal 3.0
}
}
Thanks everyone
Use a generic something to extract what you need. Your options are methods and subscripts.
protocol PlugValue {
init()
}
extension Int: PlugValue { }
extension Float: PlugValue { }
extension Double: PlugValue { }
extension SIMD3: PlugValue where Scalar == Int32 { }
struct Plug<Value: PlugValue> {
var value: Value
init(_ value: Value) {
self.value = value
}
}
protocol AnyPlug {
var anyValue: PlugValue { get }
}
extension AnyPlug {
subscript<Value: PlugValue>(type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
func callAsFunction<Value: PlugValue>(_ type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
}
extension Plug: AnyPlug {
var anyValue: PlugValue { value }
}
let plugs: [AnyPlug] = [
Plug(1),
Plug(2.3 as Float),
Plug(4.5),
Plug([6, 7, 8] as SIMD3)
]
plugs[0][Int.self] // 1
plugs[1][Double.self] // 0
plugs[1][] as Float // 2.3
let double: Double = plugs[2]() // 4.5
plugs[3](SIMD3.self).y // 7
With the array of protocols, do you have to down cast them into their Plug when retrieving them every time?
Essentially. This is true of all heterogenous sequences. Here are your options:
extension Array: PlugValue where Element: PlugValue { }
let plug: AnyPlug = Plug([0.1, 1.1, 2.1])
(plug as? Plug<[Double]>)?.value[1]
(plug.anyValue as? [Double])?[1]
extension Plug {
enum Error: Swift.Error {
case typeMismatch
}
}
extension AnyPlug {
func callAsFunction<Value: PlugValue, Return>(_ closure: (Value) -> Return) throws {
guard let value = anyValue as? Value
else { throw Plug<Value>.Error.typeMismatch }
closure(value)
}
}
try plug { (doubles: [Double]) in doubles[1] } // 1.1
try plug { ($0 as [Double])[1] } // 1.1
try plug { $0 as Int } // <Swift.Int>.Error.typeMismatch
I managed to find a solution that worked for my needs.
I am still looking at finding a better way to handle getting the data and their correct type.
import Foundation
import MetalKit
// Creating the PlugType Enum
enum PlugType{
case Integer(Int?)
case Float_(Float?)
case Double_(Double?)
case Vector3(simd_int3)
// default types
static func IntegerType() -> PlugType{ return PlugType.Integer(nil)}
static func FloatType() -> PlugType{ return PlugType.Float_(nil)}
static func DoubleType() -> PlugType{ return PlugType.Double_(nil)}
}
// Implements a way to retrieve the correct value type
extension PlugType{
var IntegerValue: Int{
switch self{
case .Integer(let value):
return value ?? 0
default:
return 0
}
}
var FloatValue: Float{
switch self
{
case .Float_(let value):
return value ?? 0
default:
return 0
}
}
var DoubleValue: Double{
switch self
{
case .Double_(let value):
return value ?? 0
default:
return 0
}
}
}
// Get the string representation of the PlugType
extension PlugType {
var typeName: String{
switch self {
case .Integer: return "Integer"
case .Float_: return "Float"
case .Double_: return "Double"
case .Vector3: return "Vector3"
}
}
var swiftType: Any.Type {
switch self {
case .Integer: return Int.self
case .Float_: return Float.self
case .Double_: return Double.self
case .Vector3: return simd_int3.self
}
}
}
class Plug{
var _value:PlugType?
var type:String? { get{ return _value?.typeName } }
init(_ newValue:PlugType){
_value = newValue
}
func geee<T>(_ input:T) -> T{
switch type {
case "Integer":
return getVal(_value!.IntegerValue) as! T
case "Double":
return getVal(_value!.DoubleValue) as! T
default:
return 0 as! T
}
}
func getVal(_ val:Int) -> Int {
return val
}
func getVal(_ val:Float) -> Float {
return val
}
func getVal(_ val:Double) -> Double {
return val
}
}
var plugs:[Plug] = []
var p1 = Plug(PlugType.Integer(2))

How to use buildExpression in Swift 5.2 Function Builders?

I understand that it's a draft proposal. I tried to implement a simple DSL for building a string, like so:
#_functionBuilder
struct StringBuilder {
static func buildExpression(_ string: String) -> [String] {
[string]
}
static func buildBlock(_ children: [String]...) -> [String] {
children.flatMap{ $0 }
}
}
func s(separator: String = "", #StringBuilder _ makeString: () -> [String]) -> String {
makeString().joined(separator: separator)
}
let z = s(separator: " ") {
"this"
"is"
"cool"
}
However, the compiler complains that "'String' is not convertible to '[String]'". This leads me to believe that buildBlock is the only part of the proposal currently implemented. (This is understandable given that in SwiftUI they are building a hierarchy of views, so that's all they need.)
Is this correct or am I doing something wrong? What is the correct way to use buildExpression?
ielyamani's answer shows how to build a working string builder such as I used in my example above. However, that does not solve the actual problem. I'm not trying to build a string builder. I'm trying to figure out function builders. The string builder is just an example. For example, if we wish to have a string builder that accepts integers, we could in theory do the following:
#_functionBuilder
struct StringBuilder {
static func buildExpression(_ int: Int) -> [String] {
["\(int)"]
}
// The rest of it implemented just as above
}
In this case, when the compiler encountered an Int, it would call buildExpression to then spit out our component type, in this case [String]. But as Martin R said in a comment to this question, buildExpression is not currently implemented.
I encountered the same issue today, it seems that buildExpression isn't implemented. I ended up making a workaround by using a protocol "ComponentProtocol" and then creating "Expression: ComponentProtocol" and "Component: ComponentProtocol". That works for me for now. I am hoping it'll be implemented later.
protocol ComponentProtocol: ExpressibleByIntegerLiteral, ExpressibleByStringLiteral {
var value: String { get }
}
struct Expression: ComponentProtocol {
let _value: String
var value: String { _value }
init(_ value: String) { _value = value }
init(integerLiteral value: Int) { self.init(value) }
init(stringLiteral value: String) { self.init(value) }
init<E: CustomStringConvertible>(_ value: E) {_value = String(describing: value) }
}
struct Component: ComponentProtocol {
let _values: [String]
var value: String { _values.joined(separator: ", ") }
init(integerLiteral value: Int) { self.init(value) }
init(stringLiteral value: String) { self.init(value) }
init<E: CustomStringConvertible>(_ value: E) { _values = [String(describing: value)] }
init<T: ComponentProtocol>(_ values: T...) { _values = values.map { $0.value } }
init<T: ComponentProtocol>(_ values: [T]) { _values = values.map { $0.value } }
}
#_functionBuilder struct StringReduceBuilder {
static func buildBlock<T: ComponentProtocol>(_ components: T ...) -> Component { Component(components) }
static func buildEither<T: ComponentProtocol>(first: T) -> Component { Component(first.value) }
static func buildEither<T: ComponentProtocol>(second: T) -> Component { Component(second.value) }
static func buildOptional<T: ComponentProtocol>(_ component: T?) -> Component? {
component == nil ? nil : Component(component!.value)
}
}
func stringsReduce (#StringReduceBuilder block: () -> Component) -> Component {
return block()
}
let result = stringsReduce {
Expression(3)
"one"
Expression(5)
Expression("2")
83
}
let s2 = stringsReduce {
if .random () { // random value Bool
Expression(11)
} else {
Expression("another one")
}
}
Since buildBlock(_:) takes a variadic number of arrays of strings, this would work:
let z = s(separator: " ") {
["this"]
["is"]
["cool"]
}
But that's still clunky. To take strings instead of Arrays of strings, add this function to StringBuilder which takes a variable number of strings:
static func buildBlock(_ strings: String...) -> [String] {
Array(strings)
}
And now you can do this:
let z = s(separator: " ") {
"Hello"
"my"
"friend!"
}
print(z) //Hello my friend!

Enum pattern matching as a parameter to a function call

I've setup a playground with an example:
enum CarType : Equatable {
case wheeled(wheels: Int)
case flying
public static func ==(lhs: CarType, rhs: CarType) -> Bool {
return lhs.enumName == rhs.enumName
}
var enumName: String {
let stuff = "\(self)".split(separator: "(").first!
return String(describing: stuff)
}
}
var typesPresentAtMyParty = [CarType.wheeled(wheels:4), .wheeled(wheels:4), .flying]
let aKnownType = CarType.flying
if case aKnownType = typesPresentAtMyParty[2] {
print("Was the type")
}
func isPresent(type: CarType, inArray: [CarType]) -> Bool {
return inArray.filter {
if case type = $0 {
return true
}
return false
}.first != nil
}
func isWheeled(inArray: [CarType]) -> Bool {
return inArray.filter {
if case .wheeled = $0 {
return true
}
return false
}.first != nil
}
isPresent(type: .flying, inArray: typesPresentAtMyParty)
isPresent(type: .wheeled, inArray: typesPresentAtMyParty)
The last line here does not compile. While i can do if case .wheeled = $0 ignoring associated type as a check, i cannot find a way of doing the same in a function call isPresent(type: CarType, inArray: [CarType]), when sending isPresent(type: .wheeled, inArray: typesPresentAtMyParty)
Is there a way of writing a function that takes only the valid pattern matching part of the enum as a parameter?
It is not possible to pass partially constructed enums to a function. Partially constructed enums are not valid values, and they only work in pattern matching because the compiler has a concrete value to work with - the one from the right side of the pattern.
These being said, you could easily rewrite your functions to better, more swiftier versions.
Firstly, you don't need isPresent, you can simply use contains:
typesPresentAtMyParty.contains { $0 == .flying }
typesPresentAtMyParty.contains { if case . wheeled = $0 { return true } else { return false } }
Similarly, isWheeled can be shortened (and renamed, for better semantics):
func isWheeled(_ carType: CarType) -> Bool {
if case . wheeled = carType { return true } else { return false }
}
which can pe passed to contains:
let hasWeeled = typesPresentAtMyParty.contains(where: isWheeled)

Swift generics: return type based on parameter type

Say I have a collection of objects inheriting from a common superclass (this is preferable to protocols in this case):
class ObjectSuperClass {
type: ObjectType
}
class ObjectClass1: ObjectSuperClass {
type = .Type1
}
class ObjectClass2: ObjectSuperClass {
type = .Type2
}
I'm looking to create a generic search function like this:
func objectsOfType<T: ObjectSuperClass>(T.class, otherFilter: Any?) -> [T]
Which could be used to search for a given sub-type, returning a more specific array of results:
let result = objectsOfType(ObjectClass2.class, otherFilter: nil) -> [ObjectClass2]
(pseudo-swift)
I feel like this is somewhere generics could help, but cannot see where constraints should be placed. Is it possible?
Well remarkably this works...
func filterType<T>(list: [AnyObject]) -> [T]
{
return list.filter{ $0 is T }.map{ $0 as! T }
}
...provided you assign the result to something that has been explicitly typed, as in the following example:
class ObjectSuperClass: CustomStringConvertible
{
let myType: String
init(aString: String)
{
myType = aString
}
var description: String { return myType }
}
class ObjectClass1: ObjectSuperClass
{
init()
{
super.init(aString: "<t 1>")
}
}
class ObjectClass2: ObjectSuperClass
{
init()
{
super.init(aString: "<t 2>")
}
}
let unfilteredList: [AnyObject] = [ ObjectClass1(), ObjectClass2(), ObjectSuperClass(aString: "<Who knows>")]
let filteredList1: [ObjectClass1] = filterType(list: unfilteredList)
print("\(filteredList1)") // <t 1>
let filteredList2: [ObjectClass2] = filterType(list: unfilteredList)
print("\(filteredList2)") // <t 2>
let filteredList3: [ObjectSuperClass] = filterType(list: unfilteredList)
print("\(filteredList3)") // [<t 1>, <t 2>, <Who knows>]
T is inferred in each case from the requested return type. The function itself filters the original array based on whether the elements are of the required type and then force casts the filtered results to the correct type.
If you want an "extra filter" you don't need to explicitly type the results as long as T can be inferred from your extra filter function.
func extraFilterType<T>(list: [AnyObject], extraFilter: T -> Bool) -> [T]
{
return list.filter{ $0 is T }.map{ $0 as! T }.filter(extraFilter)
}
let filteredList = extraFilterType(unfilteredList){
(element : ObjectClass2) -> Bool in
!element.description.isEmpty
}
print("\(filteredList)") // <t 2>
EDIT
A slicker version of the filterType function would use flatMap()
func filterType<T>(list: [Any]) -> [T]
{
return list.flatMap{ $0 as? T }
}
EDIT 2
Flatmap is deprecated for optionals, since Swift 4.something, use compactMap
func filterType<T>(list: [Any]) -> [T]
{
return list.compactMap{ $0 as? T }
}
This is the closest approximation I can come up with:
func objectsOfType<T: ObjectSuperClass>(type type: T.Type) -> [T] {
// Just returns an array of all objects of given type
}
func objectsOfType<T: ObjectSuperClass>(type type: T.Type, predicate: T -> Bool) -> [T] {
// Uses predicate to filter out objects of given type
}
Usage:
let bar = objectsOfType(type: ObjectClass1.self)
let baz = objectsOfType(type: ObjectClass2.self) {
// Something that returns Bool and uses $0
}
Technically, you can also go without type argument in the above, but then you will need to have explicitly typed receivers (bar and baz in the above example) so that Swift can correctly infer the types for you and use the right version of the generic function.
You can implement the function like this:
func objectsOfType<T: ObjectSuperClass>(objects: [ObjectSuperClass], subclass: T.Type, otherFilter: (T->Bool)?) -> [T] {
if let otherFilter = otherFilter {
return objects.filter{$0 is T && otherFilter($0 as! T)}.map{$0 as! T}
} else {
return objects.filter{$0 is T}.map{$0 as! T}
}
}
Usage example:
objectsOfType(arrayOfObjects, subclass: ObjectClass1.self, otherFilter: nil)
Note that I'm not a fan of forced casting, however in this scenario it should not cause problems.
Or, the more verbose version of the function, with one less forced cast:
func objectsOfType<T: ObjectSuperClass>(objects: [ObjectSuperClass], subclass: T.Type, otherFilter: (T->Bool)?) -> [T] {
return objects.filter({object in
if let object = object as? T {
if let otherFilter = otherFilter {
return otherFilter(object)
} else {
return true
}
} else {
return false
}
}).map({object in
return object as! T
})
}

Binary tree implementation using Swift enum

I'm doing some experiments with Swift enums to become more familiarized with them and have implemented a rudimentary binary tree. It works when adding up to three items, but adding more beyond that doesn't change it and I couldn't see why it wasn't working.
Here's the code:
protocol TreeProtocol {
mutating func insert(value: Int)
func walk()
}
enum Tree:TreeProtocol {
case Empty
case Leaf(Int)
case Node(Int, TreeProtocol?, TreeProtocol?)
init(){
self = .Empty;
}
init(value: Int) {
self = .Leaf(value)
}
init(value: Int, left:TreeProtocol?, right:TreeProtocol?){
self = .Node(value, left, right);
}
mutating func insert(value: Int) {
switch self {
case .Empty:
self = .Leaf(value)
case .Leaf(let currentNodeValue):
let newTree = Tree(value: value) // var here generates a warning
if value < currentNodeValue {
self = .Node(currentNodeValue, newTree, .None)
}
else {
self = .Node(currentNodeValue, .None, newTree)
}
case let .Node(currentNodeValue, leftNode, rightNode):
if (value < currentNodeValue) {
if leftNode == nil {
let newTree = Tree(value: value)
self = .Node(currentNodeValue, newTree, rightNode)
}
else {
var l = leftNode! // unable to call leftNode!.insert() directly
l.insert(value)
}
}
else {
if rightNode == nil {
let newTree = Tree(value: value)
self = .Node(currentNodeValue, leftNode, newTree)
}
else {
var r = rightNode!
r.insert(value)
}
}
}
}
func walk() {
switch self {
case .Empty:
print("Empty")
case .Leaf (let value):
print("\(value), ")
case .Node(let value, let leftNode, let rightNode):
if leftNode != nil {
leftNode!.walk()
}
print("\(value) ")
if (rightNode != nil) {
rightNode!.walk()
}
}
}
}
And if I run the following tests:
var tree = Tree();
tree.walk()
tree.insert(100)
tree.walk()
tree.insert(50)
tree.walk()
tree.insert(150)
tree.walk()
tree.insert(25)
tree.walk()
The output is:
Empty
100
50,
100
50,
100,
150
50,
100,
150
The 25 value is not getting added to the tree
(This code is a bit inelegant, its just the first iteration, there's several ugly parts in there that could be improved and beautified. Waiting for recursive enum functionality to be added to the Xcode beta).
Because you're mutating the internal nodes and that is actually creating a copy of them. That copy is never inserted into the tree, it's just thrown away after being modified. If after inserting into l and r you reinsert those nodes (with self = .Node(currentNodeValue, l, rightNode) and self = .Node(currentNodeValue, leftNode, r) respectively) then the tree as a whole will get updated. It's a by-value / by-reference issue.
I know you already have an answer, but I really like your implementation and thought I'd provide the code for implementing #Wain's solution and also streamline some of the nested if-else logic.
It involves a slight modification for the protocol, so that insert returns a value:
protocol TreeProtocol {
mutating func insert(value: Int) -> TreeProtocol
func walk()
}
And then the insert function can be rewritten like this:
mutating func insert(value: Int) -> TreeProtocol {
switch self {
case .Empty:
self = .Leaf(value)
case .Leaf(let currentNodeValue):
let newTree = Tree(value: value)
self = value < currentNodeValue
? .Node(currentNodeValue, newTree, .None)
: .Node(currentNodeValue, .None, newTree)
case var .Node(currentNodeValue, leftNode, rightNode):
self = value < currentNodeValue
? .Node(currentNodeValue, leftNode?.insert(value) ?? Tree(value: value), rightNode)
: .Node(currentNodeValue, leftNode, rightNode?.insert(value) ?? Tree(value: value))
}
return self
}