<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=""><div class="">It is worth noting that this is not the only case that has this “flaw”. In many of the AUMPs exposed in Foundation they are really either “out” parameters or in a few cases “inout” parameters (and I think there are a handful of “in” style parameters too).</div><div class=""><br class=""></div><div class="">The major issue for refining this in the overlay is the implementation of subclassers.</div><div class=""><br class=""></div><div class="">Lets say you have a NSScanner subclass (I am dubious on how common this is but it is a decent example).</div><div class=""><br class=""></div><div class="">If we were to add a refinement for swift of scanString the problem would be that refinement would not be called as expected by subclassers;</div><div class=""><br class=""></div><div class="">lets say we refine via overlay to:</div><div class=""><br class=""></div><div class="">class Scanner : NSObject {</div><div class="">…</div><div class="">func scanString(_ string: String, into result: inout String?) -> Bool</div><div class="">// which hides this NS_REFINED_FOR_SWIFT as:</div><div class="">func __scanString(_ string: String, into result: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool</div><div class="">…</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">class MyScanner : Scanner {</div><div class="">override func scanString(_ string: String, into result: inout String?) -> Bool { … }</div><div class="">}</div><div class=""><br class=""></div><div class="">when a MyScanner is passed into an objective-c API calling the method -[NSScanner scanString:intoString:] will invoke the __scanString swift method instead of the override of scanString (effectively making the override final).</div><div class=""><br class=""></div><div class="">This presents a big issue with NSFormatter subclasses; which are arguably more common to be subclassed than Scanner. So the funnel APIs of</div><div class=""><br class=""></div><div class="">func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool</div><div class=""><br class=""></div><div class="">probably should be written as:</div><div class=""><br class=""></div><div class="">func getObjectValue(_ obj: inout Any?, for string: String, errorDescription error: inout String?) -> Bool</div><div class=""><br class=""></div><div class="">or better yet:</div><div class="">class Formatter<Subject> : NSObject {</div><div class="">...</div><div class="">func getObjectValue(_ obj: inout Subject?, for string: String, errorDescription error: inout String?) -> Bool</div><div class="">...</div><div class="">}</div><div class=""><br class=""></div><div class="">Shy of re-implementing these classes all in swift it would be difficult with the current importing mechanisms to correct this problem. Ideally I think we should have some mechanism to annotate in, out, and inout parameters so that the intent of the API is properly exposed as well as being more swift type friendly.</div><div class=""><br class=""></div><div class="">One thought is that we could re-use the distributed object annotations for parameters as type annotations to infer to the compiler on the proper semantics of how to handle the parameters. </div><div class=""><br class=""></div><div class="">e.g.</div><div class=""><br class=""></div><div class="">- (BOOL)scanString:(NSString *)string intoString:(out NSString * _Nullable * _Nullable)result;</div><div class=""><br class=""></div><div class="">could infer to the compiler that the parameter result with the label of into would mean that it is the responsibility of this method to populate a value and similarly to error cases the boolean value determines that the populated value is actually set (else it is nil)</div><div class="">* if out is not an option then we could still interpret inout and out as swift’s inout.</div><div class=""><br class=""></div><div class="">If this were the case it would import as:</div><div class=""><br class=""></div><div class="">func scanString(_ string: String, into result: out String?) -> Bool</div><div class=""><br class=""></div><div class="">this would mean that usage could then be</div><div class=""><br class=""></div><div class="">let str: String?</div><div class="">if myScanner.scanString(“foo”, into: &str) {</div><div class="">}</div><div class=""><br class=""></div><div class="">Overall this would be safer because the variable str would be protected idiomatically from any further mutation past the initialization via the method scanString. It would also be potentially more efficient since it would could avoid autoreleasing an object. It would be valid for subclassing in that the method could be called by objc in a reasonable manner. And as a nice bonus the compiler could know about the out parameter’s optional value inside of the if guard scope (similar to guard/let, but that is perhaps icing on the cake if that would work).</div><div class=""><br class=""></div><div class="">tl;dr - I am of the opinion that most of Foundation’s APIs that are imported as AUMP are not exactly “intended” to be that and probably would be better off as something else.</div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 5, 2016, at 10:55 AM, Oliver Drobnik via swift-corelibs-dev <<a href="mailto:swift-corelibs-dev@swift.org" class="">swift-corelibs-dev@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Hello,</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">This is a repeat of an earlier post where I did not get a single response... might have fallen through the cracks...</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Earlier I posted this proposal to the Swift Evolution Mailing list. Then I looked at the NSScanner implementation in core libs and found experimental API using the return value to for returning the scanned results. See my comments on that below:</span><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">—</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Working on a function for Foundation’s Scanner I stumbled on this LLVM crash: <a href="https://bugs.swift.org/browse/SR-3295" class="">https://bugs.swift.org/browse/SR-3295</a></span><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">This got me thinking about a workaround and I would like to prose this:</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">When importing Foundation into Swift 3, all </span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">AutoreleasingUnsafeMutablePointer<T?>?</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">should instead be exposed as simple:</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">inout T?</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">e.g.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">open func scanString(_ string: String, into result: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">would become</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">open func scanString(_ string: String, into result: inout String?) -> Bool</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">The call would stay exactly the same for normal use cases where you specify a receiving variable:</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">var string: String?</b></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">scanString("=", into: &string)</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">because inout parameters require a &</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">for the use case where you don’t require a receiving parameter, a second method without result parameter would be generated:</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">open func scanString(_ string: String) -> Bool</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">This is necessary because you cannot specify nil or an immutable value for an inout parameter. </span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">A fixit/migration would change calls to</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">scanString(“foo", into result: nil)</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">into</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">scanString(“foo")</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">The normal call with receiving variable would stay the same. But the case without return would become more concise.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">What do you think?</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">kind regards</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Oliver Drobnik</span></div></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">—</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">The new experimental API does not consider the situation that one might just want to scan a token in a long string and since I know what I am scanning I don’t care about the result. For example in my scanning I would like to processed if I hit a “foo“ … </span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">The experimental API would force me to do this:</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><b class="" style="background-color: rgba(255, 255, 255, 0);">if let _ = scanString(“foo“) { }</b></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">My proposal is more elegant:</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">if scanString(“foo”) {}</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">And if you do lots and lots of these scans then performance would benefit from the compiler not having to pack the return for an autoreleasing value which would have to be released right away due to assignment to _.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">IMHO my proposal is more in line with the spirit of the original API: 1) return Bool if the scan was successful, 2) optionally return the scanned value.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">kind regards</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Oliver Drobnik</span></div><div class=""><br class=""></div></div></div>_______________________________________________<br class="">swift-corelibs-dev mailing list<br class=""><a href="mailto:swift-corelibs-dev@swift.org" class="">swift-corelibs-dev@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-corelibs-dev<br class=""></div></blockquote></div><br class=""></body></html>