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

Ramiro Feria Purón ramiro.feria.puron at gmail.com
Thu Dec 1 23:59:48 CST 2016


*I might even be willing to inhibit deduction,by default, of all generic
function type parameters that don't appear inthe parameter list.*

^ If this was adopted, what Dave is proposing is:

func f<T>() -> T             // error: generic parameter T must be explicit
func f<explicit T>() -> T   // ok



On Thu, 1 Dec 2016 at 11:17 Dave Abrahams via swift-evolution <
swift-evolution at swift.org> wrote:

>
> on Mon Nov 28 2016, Douglas Gregor <swift-evolution at swift.org> wrote:
>
> >> On Nov 21, 2016, at 3: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.
> >
> > 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.  I might even be willing to inhibit deduction,
> by default, of all generic function type parameters that don't appear in
> the parameter list.
>
> --
> -Dave
>
> _______________________________________________
> 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/20161202/98ecee73/attachment.html>


More information about the swift-evolution mailing list