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