<div dir="ltr">...assuming, of course, that you&#39;re putting forward a draft proposal about Swift that happens to be modest in scope, and not <a href="https://en.wikipedia.org/wiki/A_Modest_Proposal">a Swiftian modest proposal</a>.<div><br><br>On Fri, Apr 22, 2016 at 7:56 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com">xiaodi.wu@gmail.com</a>&gt; wrote:<br>&gt; Not an expert on Obj-C compatibility in Swift by any means, but this<br>&gt; reads like it&#39;s largely a change of nomenclature. To me, though,<br>&gt; `objcoptional` reads exceedingly poorly. Why not emphasize the Obj-C<br>&gt; compatibility angle by requiring the `@objc` attribute to precede each<br>&gt; use of `optional`? (In other words, effectively rename `optional` to<br>&gt; `@objc optional`.)<br>&gt;<br>&gt;<br>&gt; On Fri, Apr 22, 2016 at 7:35 PM, Douglas Gregor via swift-evolution<br>&gt; &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>&gt;&gt; Proposal link:<br>&gt;&gt; <a href="https://github.com/DougGregor/swift-evolution/blob/objc-optional/proposals/NNNN-optional-requirements.md">https://github.com/DougGregor/swift-evolution/blob/objc-optional/proposals/NNNN-optional-requirements.md</a><br>&gt;&gt;<br>&gt;&gt; After a whole lot of discussion and thrashing on optional requirements, I<br>&gt;&gt; have a draft for a modest proposal: change the ‘optional’ keyword to<br>&gt;&gt; something that indicates that this feature is only for compatibility with<br>&gt;&gt; Objective-C and will not be supported on Swift protocols. Comments welcome!<br>&gt;&gt;<br>&gt;&gt; - Doug<br>&gt;&gt;<br>&gt;&gt; Make Optional Requirements Objective-C-only<br>&gt;&gt;<br>&gt;&gt; Proposal: SE-NNNN<br>&gt;&gt; Author(s): Doug Gregor<br>&gt;&gt; Status: Awaiting review<br>&gt;&gt; Review manager: TBD<br>&gt;&gt;<br>&gt;&gt; Introduction<br>&gt;&gt;<br>&gt;&gt; Swift currently has support for &quot;optional&quot; requirements in Objective-C<br>&gt;&gt; protocols, to match with the corresponding feature of Objective-C. We don&#39;t<br>&gt;&gt; want to make optional requirements a feature of Swift protocols (for reasons<br>&gt;&gt; described below), nor can we completely eliminate the notion of the language<br>&gt;&gt; (for different reasons also described below). Therefore, to prevent<br>&gt;&gt; confusion about our direction, this proposal changes the optional keyword<br>&gt;&gt; objcoptional to indicate that this is an Objective-C compatibility feature.<br>&gt;&gt;<br>&gt;&gt; Swift-evolution threads: eliminate optional requirements, make Swift<br>&gt;&gt; protocols support optional requirements and make optional protocol<br>&gt;&gt; requirements first class citizens.<br>&gt;&gt;<br>&gt;&gt; Motivation<br>&gt;&gt;<br>&gt;&gt; Having optional only work for Objective-C requirements is very weird: it<br>&gt;&gt; feels like a general feature with a compiler bug that prevents it from<br>&gt;&gt; working generally. However, we don&#39;t want to make it a feature of Swift<br>&gt;&gt; protocols and we can&#39;t eliminate it (see alternatives considered), so we<br>&gt;&gt; propose to rename the keyword to make it clear that this feature is intended<br>&gt;&gt; only for compatibility with Objective-C.<br>&gt;&gt;<br>&gt;&gt; Proposed solution<br>&gt;&gt;<br>&gt;&gt; Rename the optional contextual keyword to objcoptional. Note that:<br>&gt;&gt;<br>&gt;&gt; It would read better as objc_optional or objcOptional, but keywords in Swift<br>&gt;&gt; run the words together, and<br>&gt;&gt;<br>&gt;&gt; It should not be an attribute @objcOptional because it changes the effective<br>&gt;&gt; type of the declaration. Referencing an optional requirement wraps the<br>&gt;&gt; result in one more level of optional, which is used to test whether the<br>&gt;&gt; requirement was implemented.<br>&gt;&gt;<br>&gt;&gt; This means that:<br>&gt;&gt;<br>&gt;&gt; @objc protocol NSTableViewDelegate {<br>&gt;&gt;   optional func tableView(_: NSTableView, viewFor: NSTableColumn, row: Int)<br>&gt;&gt; -&gt; NSView?<br>&gt;&gt;   optional func tableView(_: NSTableView, heightOfRow: Int) -&gt; CGFloat<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; becomes:<br>&gt;&gt;<br>&gt;&gt; @objc protocol NSTableViewDelegate {<br>&gt;&gt;   objcoptional func tableView(_: NSTableView, viewFor: NSTableColumn, row:<br>&gt;&gt; Int) -&gt; NSView?<br>&gt;&gt;   objcoptional func tableView(_: NSTableView, heightOfRow: Int) -&gt; CGFloat<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; Impact on existing code<br>&gt;&gt;<br>&gt;&gt; Any code that declares @objc protocols with optional requirements will need<br>&gt;&gt; to be changed to use the objcoptionalkeyword. However, it is trivial for the<br>&gt;&gt; migrator to update the code and for the compiler to provide Fix-Its, so the<br>&gt;&gt; actual impact on users should be small.<br>&gt;&gt;<br>&gt;&gt; Alternatives considered<br>&gt;&gt;<br>&gt;&gt; It&#39;s a fairly common request to make optional requirements work in Swift<br>&gt;&gt; protocols (as in the aforementioned threads, hereand here). However, such<br>&gt;&gt; proposals have generally met with resistance because optional requirements<br>&gt;&gt; have significant overlap with other protocol features: &quot;default&quot;<br>&gt;&gt; implementations via protocol extensions and protocol inheritance. For the<br>&gt;&gt; former case, the author of the protocol can provide a &quot;default&quot;<br>&gt;&gt; implementation via a protocol extension that encodes the default case<br>&gt;&gt; (rather than putting it at the call site). In the latter case, the protocol<br>&gt;&gt; author can separate the optional requirements into a different protocol that<br>&gt;&gt; a type can adopt to opt-in to whatever behavior they customize. While not<br>&gt;&gt; exactlythe same as optional requirements, which allow one to perform<br>&gt;&gt; per-requirement checking to determine whether the type implemented that<br>&gt;&gt; requirement, the gist of the threads is that doing so is generally<br>&gt;&gt; considered an anti-pattern: one would be better off factoring the protocol<br>&gt;&gt; in a different way. Therefore, we do not propose to make optional<br>&gt;&gt; requirements work for Swift protocols.<br>&gt;&gt;<br>&gt;&gt; The second alternative would be to eliminate optional requirements entirely<br>&gt;&gt; from the language. The primary challenge here is Cocoa interoperability,<br>&gt;&gt; because Cocoa&#39;s protocols (primarily delegates and data sources) have a<br>&gt;&gt; large number of optional requirements that would have to be handled somehow<br>&gt;&gt; in Swift. These optional requirements would have to be mapped to some other<br>&gt;&gt; construct in Swift, but the code generation model must remain the same<br>&gt;&gt; because the Cocoa frameworks rely on the ability to ask the question &quot;was<br>&gt;&gt; this requirement implemented by the type?&quot; in Objective-C code at run time.<br>&gt;&gt;<br>&gt;&gt; The most popular approach to try to map optional requirements into existing<br>&gt;&gt; Swift constructs is to turn an optional method requirement into a property<br>&gt;&gt; of optional closure type. For example, this Objective-C protocol:<br>&gt;&gt;<br>&gt;&gt; @protocol NSTableViewDelegate<br>&gt;&gt; @optional<br>&gt;&gt; - (nullable NSView *)tableView:(NSTableView *)tableView<br>&gt;&gt; viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;<br>&gt;&gt; - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row;<br>&gt;&gt; @end<br>&gt;&gt;<br>&gt;&gt; which currently imports into Swift as:<br>&gt;&gt;<br>&gt;&gt; @objc protocol NSTableViewDelegate {<br>&gt;&gt;   optional func tableView(_: NSTableView, viewFor: NSTableColumn, row: Int)<br>&gt;&gt; -&gt; NSView?<br>&gt;&gt;   optional func tableView(_: NSTableView, heightOfRow: Int) -&gt; CGFloat<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; would become, e.g.,<br>&gt;&gt;<br>&gt;&gt; @objc protocol NSTableViewDelegate {<br>&gt;&gt;   var tableView: ((NSTableView, viewFor: NSTableColumn, row: Int) -&gt;<br>&gt;&gt; NSView?)? { get }<br>&gt;&gt;   var tableView: ((NSTableView, heightOfRow: Int) -&gt; CGFloat)? { get }<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; Unfortunately, this introduces an overloaded property named tableView. To<br>&gt;&gt; really make this work, we would need to introduce the ability for a property<br>&gt;&gt; to have a compound name, which would also let us take the labels out of the<br>&gt;&gt; function type:<br>&gt;&gt;<br>&gt;&gt; @objc protocol NSTableViewDelegate {<br>&gt;&gt;   var tableView(_:viewFor:row:): ((NSTableView, NSTableColumn, Int) -&gt;<br>&gt;&gt; NSView?)? { get }<br>&gt;&gt;   var tableView(_:heightOfRow:): ((NSTableView, Int) -&gt; CGFloat)? { get }<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; By itself, that is a good feature. However, we&#39;re not dont, because we would<br>&gt;&gt; need yet another extension to the language: one would want to be able to<br>&gt;&gt; provide a method in a class that is used to conform to a property in the<br>&gt;&gt; protocol, e.g.,<br>&gt;&gt;<br>&gt;&gt; class MyDelegate : NSObject, NSTableViewDelegate {<br>&gt;&gt;   func tableView(_: NSTableView, viewFor: NSTableColumn, row: Int) -&gt;<br>&gt;&gt; NSView? { ... }<br>&gt;&gt;   func tableView(_: NSTableView, heightOfRow: Int) -&gt; CGFloat { ... }<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; Indeed, the Objective-C implementation model effectively requires us to<br>&gt;&gt; satisfy these property-of-optional-closure requirements with methods so that<br>&gt;&gt; Objective-C clients can use -respondsToSelector:. In other words, one would<br>&gt;&gt; not be able to implement these requirements in by copy-pasting from the<br>&gt;&gt; protocol to the implementing class:<br>&gt;&gt;<br>&gt;&gt; class MyDelegate : NSObject, NSTableViewDelegate {<br>&gt;&gt;   // Note: The Objective-C entry points for these would return blocks, which<br>&gt;&gt; is incorrect<br>&gt;&gt;   var tableView(_:viewFor:row:): ((NSTableView, NSTableColumn, Int) -&gt;<br>&gt;&gt; NSView?)? { return ...   }<br>&gt;&gt;   var tableView(_:heightOfRow:): ((NSTableView, Int) -&gt; CGFloat)? { return<br>&gt;&gt; ... }<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; That is both a strange technical restriction that would be limited to<br>&gt;&gt; Objective-C protocols and a serious usability problem: the easiest way to<br>&gt;&gt; stub out the contents of your type when it conforms to a given protocol is<br>&gt;&gt; to copy the declarations from the protocol into your type, then fill in the<br>&gt;&gt; details. This change would break that usage scenario badly.<br>&gt;&gt;<br>&gt;&gt; There have been other ideas to eliminate optional requirements. For example,<br>&gt;&gt; Objective-C protocols could be annotated with attributes that say what the<br>&gt;&gt; default implementation for each optional requirement is (to be used only in<br>&gt;&gt; Swift), but such a massive auditing effort is impractical. There is a<br>&gt;&gt; related notion of caller-site default implementations that was not<br>&gt;&gt; well-received due to its complexity.<br>&gt;&gt;<br>&gt;&gt; _______________________________________________<br>&gt;&gt; swift-evolution mailing list<br>&gt;&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>&gt;&gt;<br><br></div></div>