NotationMaster
NotationMaster

Reputation: 410

The Swift Programming Language - Generics - issue with Where clauses

In The Swift Programming Language book, available on the iBooks Store, in the Generics chapter, somewhere towards the end, it talks about Generic Where Clauses after having talked about constraintsand type constraints. The following protocol is given:

protocol Container {
    associated type Item: Equatable
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

The following function is then declared:

func allItemsMatch<C1: Container, C2: Container>(_ someContainer: C1, _ anotherContainer: C2) -> Bool where C1.Item == C2.Item, C1.Item: Equatable {
    // Check that both containers contain the same number of items.
    if someContainer.count != anotherContainer.count {
        return false
    }

    // Check each pair of items to see if they're equivalent.
    for i in 0..<someContainer.count {
        if someContainer[i] != anotherContainer[i] {
            return false
        }
    }

    // All items match, so return true.
    return true
}

To demonstrate this in action, the following struct had previously been declared:

struct Stack<Element>: Container {
    // original Stack<Element> implementation
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
    // conformance to the Container protocol
    mutating func append(_ item: Element) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Element {
        return items[i]
    }
}

And now we come to the issue I am getting in Xcode (v9.0, macOS 10.12.6 FYI):

var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")

var arrayOfStrings = ["uno", "dos", "tres"]

if allItemsMatch(stackOfStrings, arrayOfStrings) {
    print("All items match.")
} else {
    print("Not all items match.")
}

I am getting the following error next to the first line of the last if-elsestatement:

Cannot invoke 'allItemsMatch' with an argument list of type '(Stack2<String>, [String])'

As I have been learning to code for just three months now (and from scratch), I have no idea why this should fail, seeing that I am following the book to the letter. Could someone explain why this is throwing an error and propose a possible solution?

Upvotes: 1

Views: 77

Answers (1)

dzl
dzl

Reputation: 906

You have two issues here:

  1. You copied the protocol definition incorrectly, it should be:
protocol Container {
  associatedtype Item
  mutating func append(_ item: Item)
  var count: Int { get }
  subscript(i: Int) -> Item { get }
}

part 1

  1. You forgot to add the important line that conforms Array to Container:
extension Array: Container {}

part 2

Upvotes: 1

Related Questions