0

I've been trying to extend a swift array that hold specific type.

protocol Node {
  var nodeId: Int { get }
  var parentId: Int? { get }
  var children: [Node]  { get set }
  var level: Int { get set }
}

extension Array where Element : Node {
/**
unflatten an array of Nodes.
*/
func unflattenNodes()-> [Node] {

    func unflatten(inout parent: Node?)-> [Node] {

        var topNodes = [Node]()
        let children = self.filter{ (child: Node) in return child.parentId == parent?.nodeId ?? 0 }

        if !children.isEmpty {

            if var parent = parent {
                for var child in children {
                    child.level = parent.level + 1
                }
                parent.children = children
            }
            else {
                topNodes = children
            }

            for child in children {
                var optChild = Optional(child)
                unflatten(&optChild)
            }
        }
        return topNodes;
    }

      var optChild: Node? = nil
      return unflatten(&optChild)
 }
}

This code above won't be compiled because 'Node' is not subtype of 'Element', even though I'm extending Array of element "Node". How can I archive what I'm trying to do here in swift? I'm trying to add an instance method to [Node] to unflatten self.

2

3 Answers 3

1

The problem is that the protocol Node doesn't conform to itself: Node is not of type Node (as contradicting as it sounds), because a protocol isn't a concrete type, it's just a requirement for the conforming type.

That said, you need to replace every instance of Node in your code with Element, then it should work (can't test it right now). This is because again, you're actually not handling some value of type Node, but rather a value of a type that conforms to Node (Element in your case)

Also you made a few other mistakes in your code, I'll leave that to someone else to correct as I'm out of time.

Sign up to request clarification or add additional context in comments.

Comments

1

Right, I've plugged the code into Playground and I found three issues. The first is the one mentioned by Kametrixom which is that you need to use Element as the type everywhere in unflattenNodes. When you have fixed that and got rid of all the parent: in the calls to unflatten, you'll be left with one error

parent.children = children
error: cannot assign a value of type '[Element]' to a value of type '[Node]'
                parent.children = children
                                  ^

This is caused by the fact that the children property in the protocol is defined as [Node] and Swift can't match it to an array of Element

So you need to change the protocol

protocol Node {
    var nodeId: Int { get }
    var parentId: Int? { get }
    var children: [Self]  { get set }
    //            ^^^^^^ Here
    var level: Int { get set }
}

The children property is no longer an array of Node but an array of whatever type is conforming to the protocol, in your case, Element

Comments

1

Updating extension Array where Element : Node to extension CollectionType where Generator.Element == Node resolved the error.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.