[swift-evolution] [Pitch] Allow explicit specialization of generic functions

Callionica (Swift) swift-callionica at callionica.com
Thu May 26 12:32:06 CDT 2016


A perfectly reasonable preference. For me, "as" reads as a potential type
conversion (which I don't want) and specifying the type on the local can be
verbose in cases when a single input or output type is sufficient for
disambiguation. plus1 has 1/3 the number of types specified in the type
deduction operator example than appear in the explicitly typed local or the
as-cast code. Anyway, I hope you will consider all hinting/deduction
techniques as alternatives to your proposal so that you can say why it's
better or if it's solving a different problem.

On Wed, May 25, 2016 at 11:43 PM, David Hart <david at hartbit.com> wrote:

> I personally don't really see the advantage of those deduction operators.
> I would prefer writing:
>
> let plus1: (Int, Int) -> Int = +
> let plus2 = + as ((Int, Int) -> Int)
>
> On 26 May 2016, at 06:11, Callionica (Swift) <
> swift-callionica at callionica.com> wrote:
>
> I have an alternative you might like to consider: type deduction operators
>
> The input type deduction operator lets you put one or more types in front
> of a function to guide type deduction based on the parameters
>
> The output type deduction operator lets you put a type after a function to
> guide type deduction based on the return type
>
> This is a library-only solution that lets you not only select a
> specialization for a generic function, but also choose an overload from an
> overload set
>
> It's up to the user whether they use input, output, or both type deduction
> ops and up to them how many types they supply for input. For example, when
> you know that the overloads or generic functions you're choosing from have
> two parameters of the same type, you only need to provide a single type to
> trigger the correct type deduction (shown below with operator+).
>
> Here's the basic idea (the specific symbol used is just what I use, could
> be changed):
>
> infix operator >>> { associativity left }
>
> // Input type deduction operator
> func >>> <In, Out>(deduce: In.Type, fn: In -> Out) -> In -> Out {
>     return fn
> }
>
> // Add versions for functions with 2-5 parameters
> func >>> <In, In2, Out>(deduce: In.Type, fn: (In, In2) -> Out) -> (In,
> In2) -> Out {
>     return fn
> }
>
> // Add versions for 2-5 inputs
> func >>> <In, In2, Out>(deduce: (In.Type, In2.Type), fn: (In, In2) -> Out)
> -> (In, In2) -> Out {
>     return fn
> }
>
> // Output type deduction operator
> func >>> <In, Out>(fn: In -> Out, deduce: Out.Type) -> In -> Out {
>     return fn
> }
>
> let plus1 = Int.self >>> (+)
> let plus2 = (Int.self, Int.self) >>> (+)
>
> -- Callionica
>
>
>
>
>
>
> On Wed, May 25, 2016 at 4:17 PM, David Hart via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> Hello,
>>
>> This is a new pitch to allow explicitly specializing generic functions.
>> Notice that potential ambiguity with initialisers and how I’m currently
>> trying to avoid it. Please let me know what you think!
>>
>> David
>>
>> Allow explicit specialization of generic functions
>>
>>    - Proposal: SE-XXXX
>>    <https://github.com/apple/swift-evolution/blob/master/proposals/XXXX-allow-explicit-specialization-generic-functions.md>
>>    - Author: David Hart <https://github.com/hartbit>, Douglas Gregor
>>    <https://github.com/DougGregor>
>>    - Status: TBD
>>    - Review manager: TBD
>>
>>
>> <https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#introduction>
>> Introduction
>>
>> This proposal allows bypassing the type inference engine and explicitly
>> specializing type arguments of generic functions.
>>
>> <https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#motivation>
>> Motivation
>>
>> In Swift, generic type parameters are inferred by the argument or return
>> value types as follows:
>>
>> func foo<T>(t: T) { ... }
>>
>> foo(5) // infers T = Int
>>
>> There exists certain scenarios when a programmer wants to explicitly
>> specialize a generic function. Swift does not allow it, so we resort to
>> giving hints to the inference engine:
>>
>> let f1 = foo as ((Int) -> Void)let f2: (Int) -> Void = foolet f3 = foo<Int> // error: Cannot explicitly specialize a generic function
>> func bar<T>() -> T { ... }
>> let b1 = bar() as Intlet b2: Int = bar()let b3 = bar<Int>() // error: Cannot explicitly specialize a generic function
>>
>> This behaviour is not very consistent with generic types which allow
>> specialization:
>>
>> let array: Array<Int> = Array<Int>(arrayLiteral: 1, 2, 3)
>>
>> Therefore, this proposal seeks to make the above errors valid
>> specializations:
>>
>> let f3 = foo<Int> // explicitly specialized to (Int) -> Void let b3 = bar<Int>() // explicitly specialized to () -> Int
>>
>> An ambiguous scenario arrises when we wish to specialize initializer
>> functions:
>>
>> struct Foo<T: RawRepresentable where T.RawValue == String> {
>>     let storage: T
>>
>>     init<U: CustomStringConvertible>(_ value: U) {
>>         storage = T(rawValue: value.description)!
>>     }
>> }
>> enum Bar: String, CustomStringConvertible {
>>     case foobar = "foo"
>>
>>     var description: String {
>>         return self.rawValue
>>     }
>> }
>> let a = Foo<Bar>(Bar.foobar)
>>
>> Does this specialization specialize the struct's or the initializer's
>> generic type? The proposal solves this ambiguity by requiring initializer
>> generic type specialization to use the init syntax:
>>
>> let a = Foo<Bar>.init<Bar>(Bar.foobar)
>>
>>
>> <https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#detailed-design>Detailed
>> Design
>>
>> Function calls are fairly straight forward and have their grammar
>> modified as follows:
>>
>> *function-call-expression* → *postfix-expression­*
>> *generic-argument-clause­opt* *parenthesized-expression*
>>
>> *function-call-expression* → *postfix-expression*
>> *generic-argument-clause­opt* *­parenthesized-expression­opt*
>> *­trailing-closure­*
>>
>> To allow initializers to be called with explicit specialization, we need
>> to use the Initializer Expression. Its grammar is modified to:
>>
>> *initializer-expression* → *postfix-expression­* . *­init­*
>> *generic-argument-clause­opt*
>>
>> *initializer-expression* → *postfix-expression­* . *­init­*
>> *generic-argument-clause­opt* ( *­argument-names­* )
>>
>> <https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#impact-on-existing-code>Impact
>> on Existing Code
>>
>> This proposal is purely additive and will have no impact on existing code.
>>
>> <https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#alternatives-considered>Alternatives
>> Considered
>> Not adopting this proposal for Swift.
>>
>> _______________________________________________
>> 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/20160526/5881f74c/attachment.html>


More information about the swift-evolution mailing list