[swift-evolution] Proposal: Allow explicit type parameter specification in generic function call

Adrian Zubarev adrian.zubarev at devandartist.com
Mon Nov 21 17:35:42 CST 2016


I’m not sure what are you trying to solve here. Your code from the motivation compiles just fine in my Playground.

About the g function:

g(7) as [String]  
let _: [String] = g(7)
Personally I don’t like to see <Type> noise on functions in Swift.



-- 
Adrian Zubarev
Sent with Airmail

Am 22. November 2016 um 00:06:02, Ramiro Feria Purón via swift-evolution (swift-evolution at swift.org) schrieb:

Problem:

Currently, it is not possible to be explicit about the generic parameters (type parameters) in a generic function call. Type parameters are inferred from actual parameters:

func f<T>(_ t: T) {
    
    //..
}

f(5)            // T inferred to be Int
f("xzcvzxcvx")  // T inferred to be string 

If no type parameter is involved in the formal parameters, the type parameter needs to be used somehow as part of the return type. For example:

func g<T>(_ x: Int) -> [T] {
    
    var result: [T] = []
    
    //..
    
    return result
}

In such cases, the type parameters must be inferrable from the context:

g(7)                            // Error: T cannot be inferred
let array = g(7)                // Error: T cannot be inferred
let array: [String] = g(7)      // Ok: T inferred to be String
let array = g<String>(7)        // Error: Cannot explicitly specialise generic function



Proposed Solution:

Allow explicit type parameters in generic function call:

let _ = g<String>(7)            // Ok



Motivation:

Consider the following contrived example:

class Vehicle {
    var currentSpeed = 0
    //..
}

class Bicycle: Vehicle {
    //..
}

class Car: Vehicle {
    //..
}

@discardableResult
func processAll<T: Vehicle>(in vehicles: [Vehicle], condition: (Vehicle) -> Bool) -> [T] {
    
    var processed: [T] = []
    
    for vehicle in vehicles {
        guard let t = vehicle as? T, condition(vehicle) else { continue }
        //..
        processed.append(t)
    }
    
    return processed
}

func aboveSpeedLimit(vehicle: Vehicle) -> Bool {
    return vehicle.currentSpeed >= 100
}


let processedVehicles = processAll(in: vehicles, condition: aboveSpeedLimit)        // Uh, T inferred to be Vehicle!
let processedCars: [Car] = processAll(in: vehicles, condition: aboveSpeedLimit)     // T inferred to be Car
processAll<Bicycle>(in: vehicles, condition: aboveSpeedLimit)                       // This should be allowed under this proposal


Notes:

If necessary, the (real life) Swift code that lead to the proposal could be shared.

_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161122/2aaa3504/attachment.html>


More information about the swift-evolution mailing list