<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 27, 2016, at 10:24 PM, rintaro ishizaki <<a href="mailto:fs.output@gmail.com" class="">fs.output@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">After this proposal [SE-0049] is accepted:</div><div class=""><br class=""></div><div class="">Is the following code valid?</div><div class=""><br class=""></div><div class="">func foo(arg: @autoclosure () -> Bool) { }</div><div class="">let value: @autoclosure () -> Bool = false<br class=""></div><div class="">foo(value)</div></div></div></blockquote><div><br class=""></div><div>No, autoclosures may still only be used as parameters to functions.</div><div><br class=""></div><div>-Chris</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><br class=""></div><div class="">If so, I feel `@autoclosure T` is more natural than `@autoclosure () -> T`</div><div class=""><br class=""></div><div class="">let value: @autoclosure Bool = false</div><div class=""><div class="">func foo(arg: @autoclosure Bool) {</div><div class=""> if arg() { ... }</div><div class="">}</div></div><div class="">foo(x)</div><div class=""><br class=""></div><div class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">2016-03-10 14:38 GMT+09:00 Chris Lattner via swift-evolution <span dir="ltr" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span>:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><b class="">Introduction<br class=""></b><br class="">This proposal suggests moving the existing @noescape and @autoclosure attributes from being declaration attributes on a parameter to being type attributes. This improves consistency and reduces redundancy within the language, e.g. aligning with the previous Swift 3 decision to move “inout”, and making declaration and type syntax more consistent. <br class=""><br class="">Swift-evolution thread: <you are here><br class=""><br class=""><b class="">Motivation<br class=""></b><br class="">Chris Eidhof noticed an emergent result of removing our currying syntax: it broke some useful code using @noescape, because we only allowed it on parameter declarations, not on general things-of-function-type. This meant that manually curried code like this:<br class=""><br class="">func curriedFlatMap<A, B>(x: [A]) -> (@noescape A -> [B]) -> [B] {<br class=""> return { f in<br class=""> x.flatMap(f)<br class=""> }<br class="">}<br class=""><br class="">Was rejected. Fixing this was straight-forward (<a href="https://github.com/apple/swift/commit/c3c6beac72bc0368030f06d52c46b6444fc48dbd" target="_blank" class="">https://github.com/apple/swift/commit/c3c6beac72bc0368030f06d52c46b6444fc48dbd</a>), but required @noescape being allowed on arbitrary function types. Now that we have that, these two declarations are equivalent:<br class=""><br class=""><span style="white-space:pre-wrap" class="">        </span>func f(@noescape fn : () -> ()) {} // declaration attribute<br class=""><span style="white-space:pre-wrap" class="">        </span>func f(fn : @noescape () -> ()) {} // type attribute.<br class=""><br class="">Further evaluation of the situation found that @autoclosure (while less pressing) has the exact same problem. That said, it is currently in a worse place than @noescape because you cannot actually spell the type of a function that involves it. Consider an autoclosure-taking function like this:<br class=""><br class=""><span style="white-space:pre-wrap" class="">        </span>func f2(@autoclosure a : () -> ()) {}<br class=""><br class="">You can use it as you’d expect, e.g.:<br class=""><br class=""><span style="white-space:pre-wrap" class="">        </span>f2(print("hello”))<br class=""><br class="">Of course, f2 is a first class value, so you can assign it:<br class=""><br class=""><span style="white-space:pre-wrap" class="">        </span>let x = f2<br class=""><span style="white-space:pre-wrap" class="">        </span>x(print("hello"))<br class=""><br class="">This works, because x has type "(@autoclosure () -> ()) -> ()”. You can see this if you force a type error:<br class=""><br class=""><span style="white-space:pre-wrap" class="">        </span>let y : Int = x // error: cannot convert value of type '(@autoclosure () -> ()) -> ()' to specified type 'Int'<br class=""><br class="">However, you can’t write this out explicitly:<br class=""><br class=""><span style="white-space:pre-wrap" class="">        </span>let x2 : (@autoclosure () -> ()) -> () = f2<br class=""><span style="white-space:pre-wrap" class="">        </span>// error: attribute can only be applied to declarations, not types<br class=""><br class="">This is unfortunate because it is an arbitrary inconsistency in the language, and seems silly that you can use type inference but not manual specification for the declaration of x2.<br class=""><br class=""><b class="">Proposed solution<br class=""></b><br class="">The solution solution is straight-forward: disallow @noescape and @autoclosure on declarations, and instead require them on the types. This means that only the type-attribute syntax is supported:<div class=""><br class=""></div><div class=""><span style="white-space:pre-wrap" class="">        </span>func f(fn : @noescape () -> ()) {} // type attribute.<br class=""><span style="white-space:pre-wrap" class="">        </span>func f2(a : @autoclosure () -> ()) {} // type attribute.</div><div class=""><br class="">This aligns with the syntax used for types, since the type of “f” is “(_: @noescape () -> ()) -> ()”, and the type of “f2” is “(_ : @autoclosure () -> ()) -> ()”. This fixes the problem with x2, and eliminates the redundancy between the @noescape forms.</div><div class=""><br class=""><b class="">Impact on existing code<br class=""></b><br class="">This breaks existing code that uses these in the old position, so it would be great to roll this out with the other disruptive changes happening in Swift 3. The Swift 3 migrator should move these over, and has the information it needs to do a perfect migration in this case.</div><div class=""><br class=""></div><div class="">For the compiler behavior, given that Swift 2.2 code will be source incompatible with Swift 3 code in general, it seems best to make these a hard error in the final Swift 3 release. It would make sense to have a deprecation warning period for <a href="http://swift.org/" target="_blank" class="">swift.org</a> projects like corelibs and swiftpm, and other open source users tracking the public releases though.</div><span class="HOEnZb"><font color="#888888" class=""><div class=""><div class=""><br class=""></div><div class="">-Chris</div><div class=""><div class=""><br class=""></div><div class=""><br class=""></div></div></div></font></span></div><br class="">_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
<br class=""></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></body></html>