3

I defined a protocol LLNodeType:

protocol LLNodeType {
    typealias T
    var firstNode: LLNode<T>? { get }
}

LLNode<T> is just a simple generic class, which contains a stored property of type N.

class LLNode<N> {
    var content: N
    ...
}

To conform to the LLNodeType protocol I therefore extended LLNode as follows:

extension LLNode: LLNodeType {
    typealias T = N

    var firstNode: LLNode<T>? {
        return self
    }
}

I also defined a generic class LLLinkedList containing a few properties and functions using the generic type L:

class LLLinkedList<L> {
    var rootNode: LLNode<L>?
    ...
}

I extended this class to conform to LLNodeType:

extension LLLinkedList: LLNodeType {
    typealias T = L

    var firstNode: LLNode<T>? {
         return self.rootNode
    }
}

I found a way of passing LLNodeType to methods of LLLinkedList as a regular type and used it on the append method:

func append<NT: LLNodeType>(nodeSequence: NT) {
    let nodes = LLLinkedList(nodeSequence: nodeSequence) 
    ...
}

As seen in the first statement of the append method, I have also defined an initializer for LLLinkedList, that takes a parameter nodeSequence of type LLNodeType:

convenience init<NT: LLNodeType where NT.T == L>(nodeSequence: NT) {
    self.init()
    self.rootNode = nodeSequence.firstNode
}

The initializer only takes a nodeSequence which conforms to LLNodeType, which is constrained though to use a type T equal to L.

The firstNode property of a nodeSequence conforming to these conditions should therefore return an LLNode<L>?.

Therefore the statement self.rootNode = nodeSequence.firstNode should be completely possible, since self.rootNode is of type LLNode<L>?.


When I try to compile the code, I get the error:

<stdin>:501:33: error: extra argument 'nodeSequence' in call
let nodes = LLLinkedList(nodeSequence: nodeSequence)

501:33 refers to the first statement of the append method.

How can there be an extra argument 'nodeSequence' if I defined the initializer with an argument called nodeSequence?


Here's a code sample containing only the parts relevant to the question: SwiftStub-Code

Marcus Rossel
  • 3,196
  • 1
  • 26
  • 41
  • Can you provide a full block of code that can be cut/pasted into a playground? Otherwise it'll be too hard for someone to reproduce your problem. I just tried and the code I put together from your question (plus some tweaks such as giving `LLNode` an `init`) compiled OK. Don't get too hung up on the error message, Swift error messages are a bit misleading at the moment sometimes. Basically what it is doing is giving you the reason why it can't use the `init()` method, having ruled out your convenience method for some other reason it's not mentioning. – Airspeed Velocity Jan 30 '15 at 20:14
  • I have added a link at the bottom of the question. As it says it only contains parts relevant to the question. If you really like I could post the whole code-block, which is mostly irrelevant though. – Marcus Rossel Jan 30 '15 at 20:36
  • The link to your actual code gave me what was needed to figure out why it didn't work – what you posted in your question didn't. Always try to put into the question enough code to easily reproduce the problem when you can – you'll rarely get a good answer from code people can't easily try without having to write more... – Airspeed Velocity Jan 30 '15 at 21:06

1 Answers1

2

The problem is that your append function is not mandating the type of LLNodeType.T for the sequence you're appending:

func append<NT: LLNodeType>(nodeSequence: NT) {
    // here, nodeSequence could be of a String, an Int, who knows...
    let nodes = LLLinkedList(nodeSequence: nodeSequence) 
    ...
    // but here you try to append it to the existing list...
    // what if it's not a list of the same type?
    if self.isEmpty {
        self.rootNode = nodes.rootNode
    } else {
    /// appends a node by pointing the last nodes pointer ('nextNode' property) to the new node
        self.lastNode!.nextNode = nodes.rootNode
    }
}

You can resolve this by mandating you only append sequences of the same type as your

func append<NT: LLNodeType where NT.T == L>(nodeSequence: NT) {
    // etc...
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118