<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><br><br><div id="AppleMailSignature">Sent from my iPad</div><div><br>On Dec 3, 2017, at 10:40 AM, David Hart <<a href="mailto:david@hartbit.com">david@hartbit.com</a>> wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 3 Dec 2017, at 04:11, Matthew Johnson via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Sent from my iPad</div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class="">On Dec 2, 2017, at 7:40 PM, Chris Lattner <<a href="mailto:clattner@nondot.org" class="">clattner@nondot.org</a>> wrote:<br class=""><br class=""></div><blockquote type="cite" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class=""><div class="">On Dec 2, 2017, at 2:13 PM, Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> wrote:<div class=""><blockquote type="cite" class=""><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><div class="">For all those reasons, we really do need something like AnyObject dispatch if we care about working with dynamically typed languages. The design I’m suggesting carefully cordons this off into its own struct type, so it doesn’t infect the rest of the type system, and is non-invasive in the compiler.</div></div></div></div></blockquote><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">I am quite familiar with dynamic languages and agree that this is necessary if we are going to fully open up access to these languages from Swift.</div></div></blockquote><div class=""><br class=""></div><div class="">Ok, then it appears you agree that something like anyobject dispatch is necessary for effective dynamic language interop.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><div class="">I<span class="Apple-converted-space"> </span><i class="">strongly</i> urge you to reconsider the decision of that dynamic members must be made available with no indication at usage sites. An indication of dynamic lookup at usage sites aligns very well (IMO) with the rest of Swift (AnyObject lookup aside) by calling attention to code that requires extra care to get right.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I don’t understand this. The proposal is fully type safe, and this approach is completely precedented by AnyObject. Swift’s type system supports many ways to express fallibility, and keeping those decisions orthogonal to this proposal is the right thing to do, because it allows the author of the type to decide what model makes sense for them.</div></div></div></div></blockquote><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Allowing the author of the type to choose whether the mechanism is hidden or visible is exactly what I don’t want to allow. I think you have the right design regarding types and semantics - the author chooses. But I don’t want these calls to look like ordinary member lookup when I’m reading code. </div></div></blockquote><blockquote type="cite" class=""><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">They inherently have a much greater chance of failure than ordinary member lookup. Further, authors are likely to choose immediate traps or nil IUO as failure modes as forcing users to deal with Optional on every call is likely to be untenable. I believe this behavior should be represented by some kind of syntax at the usage site. I don’t believe it is an undue burden. It would make the dynamic lookup semantic clear to all readers and would help to discourage abuse.</div></div></blockquote><div class=""><br class=""></div><div class="">I believe that adding explicit syntax would be counterproductive to your goals, and would not make dynamic lookup syntax more clear. I assume that you would also want the same thing for DynamicCallable too, and operator overloads, subscripts, and every other operation you perform on these values, since they all have the exact same behavior.</div><div class=""><br class=""></div><div class="">If we required some syntax even as minimal as “foo.^bar” and "baz^(42)”, that change would turn this (which uses runtime failing or IUO return values like AnyObject):</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let np = Python.import("numpy")<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x = np.array([6, 7, 8])</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y = np.arange(24).reshape(2, 3, 4)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let a = np.ones(3, dtype: np.int32)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let b = np.linspace(0, pi, 3)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let c = a+b</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let d = np.exp(c)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>print(d)</div><div class=""><br class=""></div><div class="">into:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let np = Python.import("numpy")<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let b = np^.array^([6, 7, 8])</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y = np^.arange^(24)^.reshape^(2, 3, 4)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let a = np^.ones^(3, dtype: np^.int32)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let b = np^.linspace^(0, pi, 3)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let c = a+^b<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let d = np^.exp^(c)</div><div class=""><br class=""></div></div><div class="">This does not improve clarity of code, it merely serves to obfuscate logic. It is immediately apparent from the APIs being used, the API style, and the static types (in Xcode or through static declarations) that this is all Python stuff. </div></div></div></blockquote><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">It may be immediately apparent when the types involved are obviously dynamic, such as in this example where Python.import is explicitly used. However, my concern is less about the intended use case of dynamic language interop than I am that this feature will be generally available to all types in Swift. </div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">This is big change from AnyObject dispatch. It opens up the dynamism to types and contexts that<span class="Apple-converted-space"> </span><i class="">are not<span class="Apple-converted-space"> </span></i>necessarily obviously using dynamic lookup, callable, etc. Maybe this won’t turn out to be a problem in practice but I still think it’s a legitimate concern.</div></div></blockquote><div><br class=""></div><div>If dynamism if restricted to subclasses of a <b class="">DynamicObject</b> type, like Xiaodi suggested earlier, then we can protect ourselves from this dynamic dispatch being generally available to all types in Swift.</div></div></div></blockquote><div><br></div>Chris has good reasons for not wanting to use a class. More generally, designs that require subclassing a specific superclass are usually a bad idea. They should only be used with very specific and very good reasons. I’m not sure what this would buy us here. How specifically do you think this helps in ways that requiring conformance to be stated in the original type declaration will not?<div><br><blockquote type="cite"><div><div><br class=""><blockquote type="cite" class=""><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class=""><div class=""><div class=""><div class="">When you start mixing in use of native Swift types like dictionaries (something we want to encourage because they are typed!) you end up with an inconsistent mismash where people would just try adding syntax or applying fixits continuously until the code builds.</div><div class=""><br class=""></div><div class="">Beyond that, it is counterproductive to your goals, because it means that people are far less likely to use to use optional returns. Doing so (which produces a safer result) would cause a double tax in syntax, and would be a confusing jumble. I can’t bring myself to do the whole example above, one line - just converting member lookup syntax but not callable syntax - would end up:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y = np^.arange?^(24)^.reshape^?(2, 3, 4)<br class=""></div><div class=""><br class=""></div><div class="">If you made DynamicCallable also return optional it would be:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y = np^.arange?^(24)?^.reshape^?(2, 3, 4)!<br class=""></div><div class=""><br class=""></div><div class="">or something. This is such madness that no one would do that.</div></div></div></div></blockquote><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Yes, I agree. The interaction with optional chaining makes it unworkable. I hadn’t thought that all the way through. Thank you for indulging in the discussion about this idea. </div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I’m uncertain what the right answer is. I’m still not really comfortable with opening up dynamic lookup to any user-defined type without some way to indicate to readers that dynamic lookup is happening in a piece of code. Maybe there is a less localized annotation that would indicate dynamic lookup is in effect for a larger chunk of code.</div></div></blockquote><div><br class=""></div><div>I think that making dynamic calls syntactically different to readers is going too far in the direction of safety. Plus, it makes the language inconsistent as we already have AnyObject dispatch with exactly the same syntax. But I understand why you would want it if *any* type could end up being conformed to a dynamic lookupable/callable protocol. Like said above, I think that a <b class="">DynamicObject</b> type is enough protection to not bother making the syntax heavier at the point of use.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">One idea that hasn’t been explored yet is introducing a dynamic lookup effect. That would provide clean syntax at the expression level while still making it clear that dynamic lookup is happening. This probably isn’t the right approach as it would be viral and wouldn’t even indicate that the code in a specific function body even contains a dynamic lookup. I mention it mostly to broaden the conversation and thought space about what kind of approach might address my concerns without cluttering up expressions.</div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Another, potentially more viable approach would be to use an approach similar to try and the proposed async of a statement modifier (possibly also allowed at the expression level as with try and async). This could be used in conjunction with an effect as mentioned above but could also be used independently even though there isn’t a current precedent for that. Your example written with this approach might be:</div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let np = Python.import("numpy")<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let b = dynamic np.array([6, 7, 8])</span></font></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y = </span></font><span style="background-color: rgba(255, 255, 255, 0);" class="">dynamic np.arange(24).reshape(2, 3, 4)</span></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let a = </span></font><span style="background-color: rgba(255, 255, 255, 0);" class="">dynamic np.ones(3, dtype: np.int32)</span></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let b = </span></font><span style="background-color: rgba(255, 255, 255, 0);" class="">dynamic np.linspace(0, pi, 3)</span></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let c = </span></font><span style="background-color: rgba(255, 255, 255, 0);" class="">dynamic a + b</span></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let d = </span></font><span style="background-color: rgba(255, 255, 255, 0);" class="">dynamic np.exp(c)</span></div></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Note: `dynamic` is just a straw man here. This is obviously a lot of boilerplate repetition of the same modifier. I would also be perfectly happy allowing this annotation to apply to a block of code or even a whole function body. Then it might be:</div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">dynamic {</div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let np = Python.import("numpy")<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let b = np.array([6, 7, 8])</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y = np.arange(24).reshape(2, 3, 4)</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let a = np.ones(3, dtype: np.int32)</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let b = np.linspace(0, pi, 3)</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let c = a + b</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let d = np.exp(c)</span></div></div><div class="" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></div><div class="" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class="" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="background-color: rgba(255, 255, 255, 0);" class="">The most obvious objection to this is that it introduces nesting and does so in a way that only very indirectly influences control flow (through the potential for dynamic failure).</span></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">My objective certainly isn’t to make code ugly and obfuscate logic. It is simply to make the usage of dynamic features that are prone to failure at runtime immediately clear to a reader. This should be as lightweight as possible while still providing valuable information to the reader.</div><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class=""><div class=""><div class=""><div class=""><div class=""><br class=""></div></div><div class=""><br class=""></div><blockquote type="cite" class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class=""><ol start="2" class="" style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; background-color: rgb(255, 255, 255);"><li class="" style="box-sizing: border-box; margin-top: 0.25em;">Swift already has a dynamic member lookup feature, "<code class="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.0470588); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">AnyObject</code> dispatch" which does not use additional punctuation, so this would break precedent.</li></ol></blockquote><div class="">I would prefer if dynamic lookup were visible with AnyObject as well. For that reason I don’t believe it makes a good precedent to follow. In fact, I would prefer to see us go the other direction and perhaps even consider revising dynamic lookup syntax for AnyObject in the future.</div></div></blockquote><div class=""><br class=""></div><div class="">This is definitely not going to happen. The change Doug mentioned is to have AnyObject lookup return optional instead of IUO, which forces ? on the clients. Adding other syntax (like you’re suggesting) is certainly not going to happen.</div><div class=""><br class=""></div><div class="">The entire point of AnyObject dispatch is to improve syntactic elegance and clarity of code using it. There is no other reason to exist. Making code that uses it syntactically onerous completely defeats the point of having it in the first place, as I’ve mentioned before.</div></div></div></blockquote><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><span style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I agree. The interaction with optional chaining is significantly more onerous than I had considered. I should have worked through an example on my own. I do hope you will consider a less localized approach to usage-site annotation though.</span><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class=""><div class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Furthermore, your premise that Swift does not have invisibly failable operations is plainly wrong. Array subscript and even integer addition can fail. </div></div></div></blockquote><div class=""><br class=""></div><div class="">I am well aware of these behaviors. The difference IMO is that programmers tend to be well aware of these preconditions even if they also often choose to ignore them. Dynamic lookup will not be so clear. This is especially true if people use it with types that also have an API available through static lookup.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><div class="">Even the behavior of AnyObject was carefully designed and considered, and were really really good reasons for it returning IUO.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I am not trying to call into question the choices made in the past. Swift wouldn’t be the great language with a bright future that it is today without an incredibly successful migration of a large user base from Objective-C to Swift. This is a huge accomplishment and couldn’t have happened without making really good decisions about some really hard tradeoffs.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><div class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div></div></div></blockquote></div><span style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></div></blockquote></div></body></html>