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.


> 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] <mailto:[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] <mailto:[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] <mailto:[email protected]>> wrote:
>> 
>>> 
>>>> On Nov 28, 2016, at 10:11 PM, Douglas Gregor via swift-evolution 
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>> 
>>>>> 
>>>>> On Nov 21, 2016, at 3:05 PM, Ramiro Feria Purón via swift-evolution 
>>>>> <[email protected] <mailto:[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] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[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

Reply via email to