[swift-evolution] Proposal: Allow explicit type parameter specification in generic function call
Derrick Ho
wh1pch81n at gmail.com
Mon Nov 21 19:40:41 CST 2016
If you want to feed it a type rather than infer it from variable type or cast it using as! Then you can just add the type as a parameter…
func processAll<T: Vehicle>(type: T.Type, in vehicles: [Vehicle], condition: (Vehicle) -> Bool) -> [T] {
return []
}
processAll(type: Bicycle.self, in: [Vehicle()], condition: {_ in true})
> On Nov 21, 2016, at 8:24 PM, Ramiro Feria Purón via swift-evolution <swift-evolution at swift.org> wrote:
>
> Yes, it does; as it does let processedCars: [Car] = processAll(in: vehicles, condition: aboveSpeedLimit)
>
> The core of the matter is that it is nowhere stated in the call (expression) processAll(in: vehicles, condition: aboveSpeedLimit) that the specialised version processAll<Bicycle> is the one to be called.
>
> Although we are aware of the semantics, it does not read naturally and is somehow confusing. The ultimate goal is to make swift cleaner and clear. It rather feels like invoking non-specialised, non-generic function, and then casting the result to an array of a given type, which is not the case.
>
> All the best,
> Ramiro
>
> 2016-11-22 12:09 GMT+11:00 Sean Heber <sean at fifthace.com <mailto:sean at fifthace.com>>:
> Doesn't this work?
>
> processAll(in: vehicles, condition: aboveSpeedLimit) as [Bicycle]
>
> l8r
> Sean
>
> Sent from my iPad
>
> On Nov 21, 2016, at 6:11 PM, Ramiro Feria Purón via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>
>> Inferring the type of an expression from its surrounding context is not necessarily an ideal feature in a strongly typed programming language.
>>
>> The goal here is to be able to be explicit about the type, in an elegant and clear way, especially when there is no (need for a) context.
>>
>> Note that the <Type> "noise" would only be necessary when the type could not be inferred from the actual parameters (and if the current surrounding context type inference was removed, which is not part of the proposal).
>>
>> The line of code from the Motivation that does not compile is:
>>
>> processAll<Bicycle>(in: vehicles, condition: aboveSpeedLimit) // This should be allowed under this proposal
>>
>> 2016-11-22 10:35 GMT+11:00 Adrian Zubarev <adrian.zubarev at devandartist.com <mailto:adrian.zubarev at devandartist.com>>:
>> I’m not sure what are you trying to solve here. Your code from the motivation compiles just fine in my Playground.
>>
>> About the g function:
>>
>> g(7) as [String]
>> let _: [String] = g(7)
>> Personally I don’t like to see <Type> noise on functions in Swift.
>>
>>
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>>
>> Am 22. November 2016 um 00:06:02, Ramiro Feria Purón via swift-evolution (swift-evolution at swift.org <mailto:swift-evolution at swift.org>) schrieb:
>>
>>> 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 <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>
> _______________________________________________
> 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/853d60db/attachment.html>
More information about the swift-evolution
mailing list