<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 &lt;<a href="mailto:fs.output@gmail.com" class="">fs.output@gmail.com</a>&gt; 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 () -&gt; Bool) { }</div><div class="">let value: @autoclosure () -&gt; 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 () -&gt; 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="">&nbsp; &nbsp;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="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</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.&nbsp; This&nbsp;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.&nbsp;<br class=""><br class="">Swift-evolution thread: &lt;you are here&gt;<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.&nbsp; This meant that manually curried code like this:<br class=""><br class="">func curriedFlatMap&lt;A, B&gt;(x: [A]) -&gt; (@noescape A -&gt; [B]) -&gt; [B] {<br class="">&nbsp;&nbsp;&nbsp;return { f in<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.flatMap(f)<br class="">&nbsp;&nbsp;&nbsp;}<br class="">}<br class=""><br class="">Was rejected.&nbsp; 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.&nbsp; 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 : () -&gt; ()) {} &nbsp;// declaration attribute<br class=""><span style="white-space:pre-wrap" class="">        </span>func f(fn : @noescape () -&gt; ()) {} &nbsp;// type attribute.<br class=""><br class="">Further evaluation of the situation found that @autoclosure (while less pressing) has the exact same problem.&nbsp; That said, it is currently in a worse place than @noescape because you cannot actually spell the type of a function that involves it. &nbsp; Consider an autoclosure-taking function like this:<br class=""><br class=""><span style="white-space:pre-wrap" class="">        </span>func f2(@autoclosure a : () -&gt; ()) {}<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 () -&gt; ()) -&gt; ()”.&nbsp; 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 () -&gt; ()) -&gt; ()' 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 () -&gt; ()) -&gt; () = 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.&nbsp; 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 () -&gt; ()) {} &nbsp; &nbsp; &nbsp;// type attribute.<br class=""><span style="white-space:pre-wrap" class="">        </span>func f2(a : @autoclosure () -&gt; ()) {} &nbsp;// type attribute.</div><div class=""><br class="">This aligns with the syntax used for types, since the type of “f” is “(_:&nbsp;@noescape () -&gt; ()) -&gt; ()”, and the type of “f2” is “(_ : @autoclosure () -&gt; ()) -&gt; ()”.&nbsp; 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.&nbsp; 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.&nbsp; 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>