[swift-evolution] [Pitch] Move @noescape
Brent Royal-Gordon
brent at architechies.com
Fri Mar 4 23:32:43 CST 2016
>> My feeling is that we should only attach information to the *type* if it follows the value around and if, at least in principle, it would make sense in at least some other type-like contexts.
>
> I think it does, and let me illustrate why. Consider an autoclosure-taking function like this (one silly example):
>
> func f(@autoclosure a : () -> ()) {}
>
> You can use it as you’d expect, e.g.:
>
> f(print("hello”))
>
> Of course, f is a first class value, and you can assign it:
>
> let x = f
> x(print("hello"))
>
> This works, because x has type "(@autoclosure () -> ()) -> ()”. You can see this if you force a type error:
>
> let y : Int = x
> // error: cannot convert value of type '(@autoclosure () -> ()) -> ()' to specified type 'Int'
>
> However, you can’t write this out explicitly:
>
> let x2 : (@autoclosure () -> ()) -> () = f
> // error: attribute can only be applied to declarations, not types
>
> This seems dumb to me :-) you should be able to write the type for any declaration you can produce. Once you do that, it makes sense to spell the original function as:
>
> func f(a : @autoclosure () -> ()) {}
>
> for consistency. Yes, I totally get the irony of the fact that @autoclosure used to be on the type in swift 1.
How much sense does it really make to have a closure with an @autoclosure parameter, though? @autoclosure is meant to be syntactic sugar for when a function needs to control the evaluation of its parameters, like `&&` or `Result(try something())`. Does that feature make sense for closures? Even if it does, does it make sense for there to be a type error when you pass a `Foo -> Bar` where an `@autoclosure Foo -> Bar` is expected, or vice versa?
I think it might make more sense to think of your `f` as having the type `(() -> ()) -> Void` and have the @autoclosure-ness of particular parameters be something that's attached to `f` itself, not the function inside it. Just as a function's access level or @objc-ness isn't part of its type, nor is the @autoclosure-ness of its parameters.
Even if we decide we have to support @autoclosure on closures, if we turn parameter labels into a feature of the variable's name instead of its type (which I believe I've seen discussed), we will have an opportunity to specify that:
let x2(@autoclosure _:): (() -> ()) -> () = f // no parameter label
let x2(@autoclosure x:): (() -> ()) -> () = f // adding a parameter label
Or you could just shed the autoclosure-ness of the parameter by writing any of these:
let x2 = f // inferring the type
let x2: (() -> ()) -> () = f // stating it explicitly
let x2(x:): (() -> ()) -> () = f // adding a parameter label
--
Brent Royal-Gordon
Architechies
More information about the swift-evolution
mailing list