<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="">Hi All,<div class=""><br class=""></div><div class="">As a peer to the DynamicCallable proposal (<a href="https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d" class="">https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d</a>), I’d like to get your feedback on making member lookup dynamically extensible. &nbsp;My primary motivation is to improve interoperability with dynamic languages like Python, Perl, Ruby, Javascript, etc, but there are other use cases (e.g. when working with untyped JSON).</div><div class=""><br class=""></div><div class="">In addition to being a high impact on expressivity of Swift, I believe an implementation can be done in a way with changes that are localized, and thus not have significant impact on the maintainability of the compiler as a whole. &nbsp;Once the pitch phase of this proposal helps refine the details, I’ll be happy to prepare an implementation for consideration.<br class=""><div class=""><br class=""></div><div class="">In case it is useful, I’m working on cleaning up my current prototype Python bindings. &nbsp;I’ll share them in the next day or two in case they are useful to provide context. &nbsp;It is amazingly simple: less than 500 lines of Swift code (plus some small additional C header glue to work around clang importer limitations) enables impressive interoperability. &nbsp;The only problems are the verbosity addressed by this proposal and the peer DynamicCallable proposal.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div class="">Here is the canonical proposal URL:</div><div class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438" class="">https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438</a></div><div class=""><br class=""></div></div><div class="">A snapshot of the proposal is included below in case it is useful. &nbsp;Thanks in advance for help improving the proposal!</div><div class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><h1 style="box-sizing: border-box; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2; margin-top: 0px !important;" class="">Introduce User-defined "Dynamic Member Lookup" Types</h1><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><li style="box-sizing: border-box;" class="">Proposal:&nbsp;<a href="https://gist.github.com/lattner/NNNN-DynamicMemberLookup.md" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class="">SE-NNNN</a></li><li style="box-sizing: border-box; margin-top: 0.25em;" class="">Author:&nbsp;<a href="https://github.com/lattner" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class="">Chris Lattner</a></li><li style="box-sizing: border-box; margin-top: 0.25em;" class="">Review Manager: TBD</li><li style="box-sizing: border-box; margin-top: 0.25em;" class="">Status:&nbsp;<span style="box-sizing: border-box; font-weight: 600;" class="">Awaiting implementation</span></li></ul><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#introduction" aria-hidden="true" class="anchor" id="user-content-introduction" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Introduction</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">This proposal introduces a new&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">DynamicMemberLookupProtocol</code>&nbsp;type to the standard library. Types that conform to it provide "dot" syntax for arbitrary names which are resolved at runtime. It is simple syntactic sugar which allows the user to write:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class="">    a <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> someValue.<span class="pl-smi" style="box-sizing: border-box;">someMember</span>
    someValue.<span class="pl-smi" style="box-sizing: border-box;">someMember</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> a</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">and have it be interpreted by the compiler as:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class="">  a <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> someValue[<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">dynamicMember</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>someMember<span class="pl-pds" style="box-sizing: border-box;">"</span></span>]
  someValue[<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">dynamicMember</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>someMember<span class="pl-pds" style="box-sizing: border-box;">"</span></span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> a</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">Many other languages have analogous features (e.g. the composition of Objective-C's&nbsp;<a href="https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/DeclaredProperty.html" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class="">explicit properties</a>&nbsp;and underlying&nbsp;<a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class="">messaging infrastructure</a>). This sort of functionality is great for implementing dynamic language interoperability, dynamic&nbsp;<a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class="">proxy APIs</a>, and other APIs (e.g. for JSON processing).</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">Swift-evolution thread:&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class="">Discussion thread topic for that proposal</a></p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#motivation-and-context" aria-hidden="true" class="anchor" id="user-content-motivation-and-context" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Motivation and Context</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">Swift is well known for being exceptional at interworking with existing C and Objective-C APIs, but its support for calling APIs written in scripting languages like Python, Perl, and Ruby is quite lacking.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">C and Objective-C are integrated into Swift by expending a heroic amount of effort into integrating Clang ASTs, remapping existing APIs in an attempt to feel "Swifty", and by providing a large number of attributes and customization points for changing the behavior of this integration when writing an Objective-C header. The end result of this massive investment of effort is that Swift provides a&nbsp;<em style="box-sizing: border-box;" class="">better</em>&nbsp;experience when programming against these legacy APIs than Objective-C itself did.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">When considering the space of dynamic languages, three things are clear: 1) there are several different languages of interest, and they each have significant interest in different quarters: for example, Python is big in data science and machine learning, Ruby is popular for building server side apps, and even Perl is in still widely used. 2) These languages have decades of library building behind them, sometimes with&nbsp;<a href="https://pandas.pydata.org/" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class="">significant communities</a>&nbsp;and 3) there are one or two orders of magnitude more users of these libraries than there are people currently using Swift.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">While it is theoretically possible to expend the same level of effort on each of these languages and communities as has been spent on Objective-C, it is quite clear that this would both ineffective as well as bad for Swift: It would be ineffective, because the Swift community has not leverage over these communities to force auditing and annotation of their APIs. It would be bad for Swift because it would require a ton of language-specific support (and a number of third-party dependencies) onto the compiler and runtime, each of which makes the implementation significantly more complex, difficult to reason about, difficult to maintain, and difficult to test the supported permutations. In short, we'd end up with a mess.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">Fortunately for us, these scripting languages provide an extremely dynamic programming model where almost everything is discovered at runtime, and many of them are explicitly designed to be embedded into other languages and applications. This aspect allows us to embed APIs from these languages directly into Swift with no language support at all - without not the level of effort, integration, and invasiveness that Objective-C has benefited from. Instead of invasive importer work, we can write some language-specific Swift APIs, and leave the interop details to that library.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">This offers a significant opportunity for us - the Swift community can "embrace" these dynamic language APIs (making them directly available in Swift) which reduces the pain of someone moving from one of those languages into Swift. It is true that the APIs thus provided will not feel "Swifty", but if that becomes a significant problem for any one API, then the community behind it can evaluate the problem and come up with a solution (either a Swift wrapper for the dynamic language, or a from-scratch Swift reimplementation of the desired API). In any case, if/when we face this challenge, it will be a good thing: we'll know that we've won a significant new community of Swift developers.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">While it is possible today to import (nearly) arbitrary dynamic language APIs into Swift today, the resultant API is unusable for two major reasons: member lookup is too verbose to be acceptable, and calling behavior is similarly too verbose to be acceptable. As such, we seek to provide two "syntactic sugar" features that solve this problem. These sugars are specifically designed to be dynamic language independent and, indeed, independent of dynamic languages at all: we can imagine other usage for the same primitive capabilities.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">The two proposals in question are the introduction of the&nbsp;<a href="https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class=""><code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">DynamicCallable</code></a>&nbsp;protocol and a related&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">DynamicMemberLookupProtocol</code>&nbsp;proposal (this proposal). With these two extensions, we think we can eliminate the need for invasive importer magic by making interoperability with dynamic languages ergonomic enough to be acceptable.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">For example, consider this Python code:</p><div class="highlight highlight-source-python" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Dog</span>:
    <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">def</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">__init__</span>(<span class="pl-smi" style="box-sizing: border-box;">self</span>, <span class="pl-smi" style="box-sizing: border-box;">name</span>):
        <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">self</span>.name <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> name
        <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">self</span>.tricks <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> []    <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">#</span> creates a new empty list for each dog</span>
        
    <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">def</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">add_trick</span>(<span class="pl-smi" style="box-sizing: border-box;">self</span>, <span class="pl-smi" style="box-sizing: border-box;">trick</span>):
        <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">self</span>.tricks.append(trick)</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">we would like to be able to use this from Swift like this (the comments show the corresponding syntax you would use in Python):</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class="">  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> import DogModule</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> import DogModule.Dog as Dog    // an alternate</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> Dog <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> Python.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">import</span>(“DogModule.<span class="pl-smi" style="box-sizing: border-box;">Dog</span><span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)<span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);">  // dog = Dog(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>Brianna<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)<span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);">  let dog = Dog(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>Brianna<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)<span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);">  // dog.add_trick(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>Roll over<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)<span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);">  dog.add_trick(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>Roll over<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)<span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);">  // dog2 = Dog(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>Kaylee<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>).add_trick(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>snore<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)<span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);">  let dog2 = Dog(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>Kaylee<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>).add_trick(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>snore<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)<span class="pl-ii" style="box-sizing: border-box; color: rgb(250, 251, 252); background-color: rgb(179, 29, 40);"></span></span></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">Of course, this would also apply to standard Python APIs as well. Here is an example working with the Python&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">pickle</code>API and the builtin Python function&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">open</code>:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class="">  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> import pickle</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> pickle <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> Python.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">import</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>pickle<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)

  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> file = open(filename)</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> file <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> Python.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">open</span>(filename)

  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> blob = file.read()</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> blob <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> file.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">read</span>()

  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> result = pickle.loads(blob)</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> result <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> pickle.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">loads</span>(blob)</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">This can all be expressed today as library functionality written in Swift, but without this proposal, the code required is unnecessarily verbose and gross. Without it (but&nbsp;<em style="box-sizing: border-box;" class="">with</em>&nbsp;the related&nbsp;<a href="https://gist.github.com/lattner/a6257f425f55fe39fd6ac7a2354d693d" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none;" class=""><code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">DynamicCallable</code>&nbsp;proposal</a>&nbsp;the code would have explicit member lookups all over the place:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class="">  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> import pickle</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> pickle <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> Python.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">get</span>(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">member</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>import<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)(<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>pickle<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)

  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> file = open(filename)</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> file <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> Python.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">get</span>(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">member</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>open<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)(filename)

  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> blob = file.read()</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> blob <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> file.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">get</span>(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">member</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>read<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)()

  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> result = pickle.loads(blob)</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> result <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> pickle.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">get</span>(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">member</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>loads<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)(blob)

  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> dog2 = Dog("Kaylee").add_trick("snore")</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> dog2 <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">Dog</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Kaylee<span class="pl-pds" style="box-sizing: border-box;">"</span></span>).<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">get</span>(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">member</span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>add_trick<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)(<span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box;">"</span>snore<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">While this is a syntactic sugar proposal, we believe that this expands Swift to be usable in important new domains. In addition to dynamic language interoperability, this sort of functionality is useful for other APIs, e.g. when working with dynamically typed unstructured data like JSON, which could provide an API like&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">jsonValue?.jsonField1?.jsonField2</code>where each field is dynamically looked up.</p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#proposed-solution" aria-hidden="true" class="anchor" id="user-content-proposed-solution" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Proposed solution</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">We propose introducing this protocol to the standard library:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">protocol</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">DynamicMemberLookupProtocol</span> {
  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">associatedtype</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">DynamicMemberLookupValue</span>

  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">subscript</span>(dynamicMember name<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">String</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">-&gt;</span> DynamicMemberLookupValue { <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">get</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">set</span> }
}</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">It also extends the language such that member lookup syntax (<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">x.y</code>) - when it otherwise fails (because there is no member&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">y</code>&nbsp;defined on the type of&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">x</code>) and when applied to a value which conforms to&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">DynamicMemberLookupProtocol</code>- is accepted and transformed into a call to the subscript in the protocol. This ensures that no member lookup on such a type ever fails.</p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#example-usage" aria-hidden="true" class="anchor" id="user-content-example-usage" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Example Usage</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">While there are many potential uses of this sort of API (e.g. resolving JSON members to named results, producing optional bindings) a motivating example comes from a prototype Python interoperability layer. There are many ways to implement this, and the details are not particularly important, but it is perhaps useful to know that this is directly useful to address the motivation section described above. Given a currency type of PyVal (and a conforming implementation named&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0.4em; margin: 0px; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;" class="">PyRef</code>), an implementation may look like:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">extension</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">PyVal</span> {
  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">subscript</span>(dynamicMember member<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">String</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">-&gt;</span> PyVal {
    <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">get</span> {
      <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> result <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">PyObject_GetAttrString</span>(borrowedPyObject, member)<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">!</span>
      <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">return</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">PyRef</span>(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">owned</span>: result)  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> PyObject_GetAttrString returns +1 result.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>    }
    <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">set</span> {
      <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">PyObject_SetAttrString</span>(borrowedPyObject, member,
                             newValue.<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">toPython</span>().<span class="pl-smi" style="box-sizing: border-box;">borrowedPyObject</span>)
    }
  }
}</pre></div><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#source-compatibility" aria-hidden="true" class="anchor" id="user-content-source-compatibility" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Source compatibility</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">This is a strictly additive proposal with no source breaking changes.</p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#effect-on-abi-stability" aria-hidden="true" class="anchor" id="user-content-effect-on-abi-stability" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Effect on ABI stability</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">This is a strictly additive proposal with no ABI breaking changes.</p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#effect-on-api-resilience" aria-hidden="true" class="anchor" id="user-content-effect-on-api-resilience" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Effect on API resilience</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">This has no impact on API resilience which is not already captured by other language features.</p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#alternatives-considered" aria-hidden="true" class="anchor" id="user-content-alternatives-considered" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Alternatives considered</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">A few alternatives were considered:</p><h3 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; font-size: 1.25em; line-height: 1.25; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#add-ability-to-provide-read-only-members" aria-hidden="true" class="anchor" id="user-content-add-ability-to-provide-read-only-members" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add ability to provide read-only members</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">The implementation above does not allow an implementation to statically reject members that are read-only. If this was important to add, we could add another protocol to model this, along the lines of:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal;" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">protocol</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">DynamicMemberLookupGettableProtocol</span> {
  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">associatedtype</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">DynamicMemberLookupValue</span>

  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> gettable only</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">subscript</span>(dynamicMember name<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">String</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">-&gt;</span> DynamicMemberLookupValue { <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">get</span> }
}

<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">protocol</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">DynamicMemberLookupProtocol</span> : <span class="pl-e" style="box-sizing: border-box; color: rgb(111, 66, 193);">DynamicMemberLookupGettableProtocol </span>{
  <span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"><span class="pl-c" style="box-sizing: border-box;">//</span> gettable and settable.</span>
<span class="pl-c" style="box-sizing: border-box; color: rgb(106, 115, 125);"></span>  <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">subscript</span>(dynamicMember name<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">:</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">String</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">-&gt;</span> DynamicMemberLookupValue { <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">get</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">set</span> }
  }</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">This would allow a type to implement one or the other based on their capabilities. This proposal starts with a very simple design based on the requirements of dynamic languages (which have no apparent immutability model), but if there is demand for this (e.g. because we want input JSON values to be gettable but not settalbe), the author is happy to switch to this more general model.</p><h3 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; font-size: 1.25em; line-height: 1.25; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#naming" aria-hidden="true" class="anchor" id="user-content-naming" style="box-sizing: border-box; color: rgb(3, 102, 214); text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Naming</h3><div style="box-sizing: border-box; margin-top: 0px; color: rgb(36, 41, 46); font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; font-variant-ligatures: normal; orphans: 2; widows: 2; margin-bottom: 0px !important;" class="">There is a lot of grounds to debate naming of the protocol and methods in this type. Suggestions (along with rationale to support them) are more than welcome.</div></div></div><div class=""><br class=""></div></body></html>