[swift-evolution] [Pitch] Allow explicit specialization of generic functions
Callionica (Swift)
swift-callionica at callionica.com
Wed May 25 23:11:30 CDT 2016
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-clauseopt* *parenthesized-expression*
>
> *function-call-expression* → *postfix-expression*
> *generic-argument-clauseopt* *parenthesized-expressionopt*
> *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-clauseopt*
>
> *initializer-expression* → *postfix-expression* . *init*
> *generic-argument-clauseopt* ( *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/20160525/d09b1ad1/attachment.html>
More information about the swift-evolution
mailing list