Why doesn't the following code work? And what do I need to change to make it work?
//: Playground - noun: a place where people can play
import Cocoa
struct Person: CustomDebugStringConvertible, Hashable {
let name: String
let age: Int
// MARK: CustomDebugStringConvertible
var debugDescription: String {
return "\(name) is \(age) years old"
}
// MARK: Hashable
var hashValue: Int {
return name.hashValue ^ age.hashValue
}
}
func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}
let ilse = Person(name: "Ilse", age: 33)
let mark = Person(name: "Mark", age: 38)
extension Collection where Iterator.Element: Person {
var averageAge: Int {
let sum = self.reduce(0) { $0 + $1.age }
let count = self.count as! Int
return sum / count
}
}
var people = [Person]()
people.append(ilse)
people.append(mark)
let averageAge = people.averageAge
I figured out that if I make the struct a Swift class it works. Does it have something to do with the struct being a value type? I do see a compiler error on the last line. "'[Person]' is not convertible to '<>'"
Thank you.
extension Collection where Iterator.Element: Person
restricts Iterator.Element
to types which adopt the protocol Person
or are a subclass of Person
. Both is not possible with
struct Person
, and in the full compiler log you'll find
error: type 'Iterator.Element' constrained to non-protocol type 'Person'
What you probably mean is
extension Collection where Iterator.Element == Person
which restricts the extension to collections of Person
.
Alternatively, define a protocol
protocol HasAge {
var age: Int { get }
}
adopt that by Person
struct Person: CustomDebugStringConvertible, Hashable, HasAge { ... }
and define the extension for collections of elements which have a age:
extension Collection where Iterator.Element: HasAge { ... }