Sent from my iPhone > On 30 Nov 2016, at 06:40, David Hart via swift-evolution > <[email protected]> wrote: > > For example, here is a design pattern I would find clearer with explicit type > information: > > let cat = factory.get<Cat>() > > vs > > let cat: Cat = factory.get() > > Having the explicit type information in angle brackets allows us to move the > type information closer to where it make sense. >
Agreed :). > >>> On 29 Nov 2016, at 23:52, Douglas Gregor via swift-evolution >>> <[email protected]> wrote: >>> >>> >>> On Nov 29, 2016, at 8:00 AM, Derrick Ho via swift-evolution >>> <[email protected]> wrote: >>> >>> I don't think the angle brackets adds any additional benefit than adding >>> the type information as a parameter. Adding Angle brackets will just make >>> it more crowded…. >> >> Adding the type information as a parameter effectively disables type >> inference for that parameter, because you have to pass the parameter >> explicitly. In some cases, like the unsafeBitCast function I pointed out, >> that is a good thing. In other cases, type inference might do the right >> thing for most callers, but specific call sites want the extra control >> provided by explicitly specifying generic arguments. That’s how I see this >> proposal: not as a replacement for the metatype parameter idiom that >> unsafeBitCast uses, but as a way to be more explicit at particular call >> sites when type inference either fails (e.g., due to lack of contextual type >> information), produces a result different than what is desired, or is >> sufficiently complicated that the call site requires more documentation. >> >>> plus, the syntax just seems too much like c++ >> >> Lots of languages use angle brackets like this; Swift has it for types >> already, so I find this an odd criticism. >> >> - Doug >> >>> On Tue, Nov 29, 2016 at 8:43 AM Goffredo Marocchi via swift-evolution >>> <[email protected]> wrote: >>> I think this is a case where the angle bran jets is both more readable and >>> terse without losing context... opinions and all :). >>> >>> Sent from my iPhone >>> >>>> On 29 Nov 2016, at 09:47, Andrew Trick via swift-evolution >>>> <[email protected]> wrote: >>>> >>>> >>>>>> On Nov 28, 2016, at 10:11 PM, Douglas Gregor via swift-evolution >>>>>> <[email protected]> wrote: >>>>>> >>>>>> >>>>>> On Nov 21, 2016, at 3:05 PM, Ramiro Feria Purón via swift-evolution >>>>>> <[email protected]> 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… >>>> >>>> Angle brackets in function calls are hideous. This is objectively more >>>> clear and much prettier IMO: >>>> >>>> unsafeBitCast(something, to: Int) >>>> >>>>> it would enable type inference to go wild with unsafe casts: >>>>> >>>>> foo(unsafeBitCast(something)) // just cast it to.. whatever >>>>> >>>>> which is… not great. >>>>> >>>>> I’d like one bit of clarification in the proposal. Right now, one is not >>>>> permitted to have a type parameter in a generic function that isn’t used >>>>> somewhere in its signature, e.g., >>>>> >>>>> func f<T>() -> Void { … } // error: T is not part of the signature of >>>>> f() >>>>> >>>>> This restriction is obvious in today’s Swift, because there is absolutely >>>>> no way one could ever use this function. With your proposed extension, it >>>>> would be possible to use this function. Does the restriction remain or is >>>>> it lifted? >>>>> >>>>> Personally, I’d like the restriction to stay, because it feels like such >>>>> functions fall into the same camp as unsafeBitCast: if the type parameter >>>>> affects how the function operates but is *not* part of its signature, >>>>> then it should be expressed like a normal parameter (of a metatype). It >>>>> also helps provide better diagnostics when changing a generic function to >>>>> no longer require one of its type parameters. >>>> >>>> +1 for required type parameters being normal parameters. >>>> >>>> I think the case mentioned in the proposal reads much better as: >>>> >>>> processAll(in: vehicles, as: Bicycle, condition: aboveSpeedLimit) >>>> >>>> If angle brackets can be limited to generic definitions and type names, >>>> that’s a great accomplishment. >>>> >>>> -Andy >>>> >>>>> >>>>> And, as Dave notes, it’s effectively syntactic sugar, so it belongs in >>>>> Swift 4 stage 2. >>>>> >>>>> - Doug >>>>> >>>>> >>>>> _______________________________________________ >>>>> swift-evolution mailing list >>>>> [email protected] >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
