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

Benjamin Spratling bspratling at mac.com
Mon Nov 21 19:39:40 CST 2016


I don’t understand how your “contrived example" could be improved by this new feature instead of existing features.
It sounds like you’re trying to combine two entirely different things into one function.  One is a filter, which is easily made with .flatMap

let vehicles:[Vehicle] = [Bicycle(), Car()]
let cars = vehicles.flatMap { (vehicle) -> Car? in
	return vehicle as? Car
}	//[Car]
//cars is an Array<Car>

Since your processAll func would be restricted to Vehicle subclasses anyway, you won’t be calling any sub-class specific code on them without making explicit references to them, so do you need the type casting for anything other than the return?

If so, consider passing the exact class in as an argument:

func process(in vehicles:[Vehicle], type:Vehicle.Type) {
	for vehicle in vehicles {
		if type(of:car) != type) { continue }
		
So, I’m not convinced that your “contrived example" are best solved with a new language feature.

-Ben


> On Nov 21, 2016, at 5:05 PM, Ramiro Feria Purón via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 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/20161121/501c8446/attachment.html>


More information about the swift-evolution mailing list