<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="">James,<div class=""><br class=""></div><div class="">We did consider an availability model with feature detection similar to the one you proposed. This is essentially the model that Objective-C has. We’ve found that there are significant drawbacks to that model and believe that version checks + compile-time checking offer a better user experience.</div><div class=""><br class=""></div><div class="">* Compile-time checking of availability makes version checking less fragile.</div><div class=""><br class=""></div><div class="">A key component of Swift’s availability model is that — unlike in Objective-C or JavaScript — any use of an API element is verified for availability by the compiler. This eliminates the main source of fragility in the version checking model: getting a version check wrong and calling the API anyway. The compiler makes the strong guarantee that it will detect this and inform the developer that they have made a mistake.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div class="">* Feature detection checks are hard to reason about and test.</div><div class=""><br class=""></div><div class="">With version checks it is is immediately obvious on what environment the code will execute. This makes it easy to reason about, for example, how to test the given class/method/branch. In contrast, with feature detection even determining when a given branch of an availability check will execute requires a trip to the documentation. A polyfill model would make this even more challenging because the feature could be available earlier than the documentation states!</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">* SPI and direct feature detection.&nbsp;</div><div class=""><br class=""></div><div class="">Apple sometimes adds features first as SPI and only later makes them available as API, potentially changing behavior when doing so. This means that a naive check for the presence of, say, a class or method, does not necessarily make it safe to call. For example, Apple added UINib as API in iOS 4, but earlier versions used an incompatible class with the same name. In this case, the Objective-C idiom checking for the feature effectively “lied” about UINib’s availability. When it comes to API, the run-time checks for #available need to allow symbols to be present but still not considered available. Version checks (either OS versions or library versions) are one mechanism to do this.</div><div class=""><div class=""><br class=""></div></div><div class=""><br class=""></div><div class=""><div class="">* Dead check detection</div></div><div class=""><br class=""></div><div class="">One nice aspect of version checks is that it gives the compiler the ability to detect availability checks that are no longer needed because the application is being deployed only on versions of the OS on which the check would always succeed. This is not possible with a direct feature detection model alone (it still needs APIs to be annotated with their versions) and would help prevent older codebases from being littered with feature checks falling back to effectively dead code that no one knows whether it is safe to remove or not.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">* Overloading makes it verbose to check for a feature.</div><div class=""><br class=""></div><div class="">Swift’s support for function and method overloads makes it quite verbose to check for existence of a feature. Unambiguously identifying a method in a #available check would require specifying its parameter types and even constraints on generic type parameters.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">* Features are often correlated.</div><div class=""><br class=""></div><div class="">In Objective-C codebases we find that developers often make implicit assumption about OS versions even when using direct feature checks. For example, a developer will often check for the existence of one method and then perform an unguarded use of another method that was introduced in the same version. With a direct feature detection model, the developer would have to check for each of these features separately — even though they know they were introduced in the same OS version! The fact that Objective-C developers are already skipping checks for correlated features shows that their mental model is already based on versions, so it makes sense to match that model in the affordances exposed by the language.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">All that said, polyfill is a widely used technique and it would be interesting to see what it would take to *safely* integrate into Swift. In my view, the two key challenges there are (1) compatibility (whose polyfill wins when two libraries try to polyfill the same thing?) and (2) how to make assume-guarantee @available() annotations with polyfill/feature detection safe at compile time and efficient without leaking implementation details to clients (we don’t want every function to have to list all the functions it calls [and all the functions they call, etc.] in its @available() annotation!).</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Devin</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div><blockquote type="cite" class=""><div class="">On Feb 2, 2016, at 2:03 AM, James Campbell via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Coming from a web background (before my iOS career) to me #avaliable has huge problem. It encourages fragility.<div class=""><br class=""></div><div class="">In my eyes we should encourage two types of detection: Features to make code more adaptable to different environments and language version detection: so we can understand the actual code.</div><div class=""><br class=""></div><div class="">See this example below:</div><div class=""><br class=""></div><div class="">func magic(object: Object)</div><div class="">{</div><div class="">&nbsp; if(#avaliable(9.0, 10))</div><div class="">&nbsp;{</div><div class="">&nbsp;&nbsp;object.foo()</div><div class="">&nbsp;}</div><div class="">}</div><div class=""><br class=""></div><div class="">Ideally for me I would love to check if the foo function exists like so:</div><div class=""><br class=""></div><div class=""><div class="">func iOS9OnlyProtocolFunction(object: Object)</div><div class="">{</div><div class="">&nbsp; if(#avaliable(Object.foo))</div><div class="">&nbsp;{</div><div class="">&nbsp; &nbsp;&nbsp;object.foo()</div><div class="">&nbsp;}</div><div class="">else&nbsp;</div><div class="">{</div><div class="">&nbsp;&nbsp;object.baz()</div><div class="">&nbsp;}</div><div class="">}</div><div class=""><br class=""></div><div class="">I think this encourages feature detection which results in less fragile code. What I would love to do is also to extend this to extensions so we could encourage polyfills.</div><div class=""><br class=""></div><div class="">extend object where not_avaliable(Object.foo)&nbsp;</div><div class="">{</div><div class="">&nbsp; func foo()&nbsp;</div><div class="">&nbsp;{</div><div class="">&nbsp; &nbsp;//Polyfill for platforms which don't support the Object.foo method</div><div class="">&nbsp;}</div><div class="">}</div><div class=""><br class=""></div><div class="">Not sure about compiler details but being able to polyfill the function results in much cleaner code for me. I love this approach from the web, so I created my own Objective-C Library to do this:</div><div class=""><br class=""></div><div class=""><a href="https://github.com/jcampbell05/Polly" class="">https://github.com/jcampbell05/Polly</a><br class=""></div><div class=""><div class="gmail_signature"><div dir="ltr" class=""><div class=""><div dir="ltr" class=""><p class=""><b class=""><font color="#cc0000" class="">___________________________________</font></b></p><p class=""><b class="">James⎥Lead Engineer</b></p><p class=""><b class=""><font color="#cc0000" class=""><a href="mailto:james@supmenow.com" target="_blank" class="">james@supmenow.com</a>⎥<a href="http://supmenow.com/" target="_blank" class="">supmenow.com</a></font></b></p><p class=""><b class=""><font size="2" class="">Sup</font></b></p><p class=""><b class=""><font size="2" class="">Runway East
</font></b></p><p class=""><b class=""><font size="2" class="">10 Finsbury Square</font></b></p><p class=""><b class=""><font size="2" class="">London</font></b></p><p class=""><b class=""><font size="2" class="">
EC2A 1AF&nbsp;</font></b></p></div></div></div></div></div>
</div></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>