Swift Generics Type Inference Extensions

I'm trying to build my understanding of Generics in Swift by creating a Min and Max extension for the Array class (similar to the Min and Max Extension methods in C #). There might be a better way to do this, but as I said, it just helps me understand Generics.

I created the following code:

extension Array {
    func max<T, U : Comparable>(f: T -> U ) -> U? {
        var maxSoFar : U? = nil
        for i in self {
            var itemValue = f(i as T)
            if(maxSoFar == nil) {
                maxSoFar = itemValue
            }
            if itemValue > maxSoFar {
                maxSoFar = itemValue
            }
        }
        return maxSoFar
    }

    func min<T, U : Comparable>(f: T -> U ) -> U? {
        var minSoFar : U? = nil
        for i in self {
            var itemValue = f(i as T)
            if(minSoFar == nil) {
                minSoFar = itemValue
            }
            if itemValue < minSoFar {
                minSoFar = itemValue
            }
        }
        return minSoFar
    }
}

      

To test, I created a base Person class:

class Person {
    var name : String
    var age : Float

    init(name: String, age: Float) {
        self.name = name
        self.age = age
    }
}

      

This seems to work well for these cases when I am explicit in the closure:

var maximumAge = [Person(name: "Bob", age: 42), Person(name:"Mary", age:40)]
    .max{ (p: Person) in p.age }! // Gives 42

var min = [100, 101].min{ (i: Int) in i }! // Gives 100

      

However, I cannot get it to deduce the types to use the edge-shorthand case:

var maximumAge = [Person(name: "Bob", age: 42), Person(name:"Mary", age:40)]
    .max{ $0.age }! // Error

var min = [100, 101].min{ $0 }! // Error

      

Or medium length:

var maximumAge = [Person(name: "Bob", age: 42), Person(name:"Mary", age:40)]
    .max{p in p.age }! // Error

var min = [100, 101].min{ i in i }! // Error

      

If anyone else is an expert on this subject, can you let me know what I am doing wrong? I must admit it took quite a bit of reading and hacking for me to get to this!

Thanks for any answers

+3


source to share


1 answer


When you define max

(s min

) like this:

func max<T, U : Comparable>(f: T -> U ) -> U?

      

In fact, you are saying that the closure f

can be of a different type than the elements in Array

. Since it is Array

already a generic structure Array<T>

, you can reuse an element type T

that it has already defined. From the Swift Language Guide :

When extending a generic type, you do not specify the type parameter as part of the extension definition. Instead, the type parameter list from the original type definition is available within the body of the extension, and the parameter names of the original type are used to denote the type parameters from the original type definition.



So, since the element type is T

already available to you, just take T

out the type parameters from the list, for example:

func max<U : Comparable>(f: T -> U ) -> U?

      

This ensures that the closure f

is of the same type T

as the elements in Array

. The compiler can then correctly identify the types you are using in your test cases and fix the errors you see.

+3


source







All Articles