[swift-evolution] [Pitch] Flattening the function type of unapplied instance methods
Nicola Salmoria
nicola.salmoria at gmail.com
Sat Feb 27 00:55:55 CST 2016
I think this would nicely combine with what is being said in this other thread:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160222/011132.html
I.e. it would allow to define an asymmetric method like
public protocol IntegerArithmeticType {
public func adding(to: Self) -> Self
}
and then access it as a symmetric method to implement an operator:
public func +<T: IntegerArithmeticType>(lhs: T, rhs: T) -> T {
return T.adding(lhs, rhs)
}
it would make everything more consistent, I think.
—
Nicola
> Today, you can reference an instance property as a member of its type to access it as a fully unbound function, which is currently curried:
>
> struct Foo {
> var x: Int
> func foo(y y: Int) { return x + y }
> }
>
> let foo = Foo.foo
> foo(Foo(x: 1))(y: 2) // returns 3
>
> However, this is problematic for `mutating` methods. Since the first argument is `inout`, the mutation window for the parameter formally ends before the second argument can be applied to complete the call. Currently we miscompile this, and form a closure over a dangling pointer, leading to undefined behavior:
>
> struct Bar {
> var x = 0
> mutating func bar() { x += 1 }
> }
>
> let bar = Bar.bar
> var a = Bar()
> bar(&a)() // This might appear to work, if we don't optimize too hard
>
> let closure: () ->()
> do {
> var b = Bar()
> closure = bar(&b)
> }
> closure() // This scribbles dead stack space
>
> var c = Bar() {
> didSet { print("c was set") }
> }
>
> bar(&c)() // This will scribble over c after didSet is called, if not worse
>
> We can close this hole by disallowing a reference to Bar.bar, like we already disallow partial applications. However, I think it would be in line with our other simplifications of the function type system to change the type of `Bar.bar` and other unapplied instance method references to no longer be curried. In addition to providing a model for unapplied instance methods that works with mutating methods, this would also eliminate a type difference between free functions and methods of the same arity, allowing for easier code reuse. For instance, `reduce` takes a closure of type (State, Element) ->State. Flattening the formal type of instance methods would allow binary methods to be used as-is with `reduce`, like binary free functions can:
>
> func sumOfInts(ints: [Int]) ->Int {
> return ints.reduce(0, combine: +)
> }
> func unionOfSets<T>(sets: [Set<T>]) ->Set<T>{
> return ints.reduce([], combine: Set.union)
> }
>
> What do you all think?
>
> -Joe
>
>
>
More information about the swift-evolution
mailing list