> On Nov 30, 2016, at 4:09 PM, Dave Abrahams via swift-evolution > <swift-evolution@swift.org> wrote: > > > on Mon Nov 28 2016, Douglas Gregor <swift-evolution@swift.org > <mailto:swift-evolution@swift.org>> wrote: > >>> On Nov 21, 2016, at 3:05 PM, Ramiro Feria Purón via swift-evolution >> <swift-evolution@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. >> >> This seems completely reasonable to me. I had always expected us to >> implement this feature, but we never got around to it, and it wasn’t a >> high priority because one can always use type inference. Additionally, >> there were a few places where we originally thought we wanted this >> feature, but prefer the more-explicit form where the user is required >> to explicitly pass along a metatype. unsafeBitCast is one such case: >> >> func unsafeBitCast<T, U>(_ x: T, to: U.Type) -> U >> >> Even if we had the ability to provide explicit type arguments, we >> would *not* want to change this signature to >> >> func unsafeBitCast<U, T>(_ x: T) -> U // bad idea >> >> because while it makes the correct usage slightly cleaner: >> >> unsafeBitCast<Int>(something) // slightly prettier, but... >> >> it would enable type inference to go wild with unsafe casts: >> >> foo(unsafeBitCast(something)) // just cast it to.. whatever >> >> which is… not great. > > Yeah, but IMO ideally we'd have a way to inhibit deduction of some > generic type parameters.
Well, I’d say we already have it: it’s the pass-a-metatype approach already used by unsafeBitCast, and I think usages of that API read really, really well as it is. > I might even be willing to inhibit deduction, > by default, of all generic function type parameters that don't appear in > the parameter list. I’m not a fan of this for the reasons I and Ramiro outlined. - Doug
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution