<div dir="ltr">There’s a lot of information here and it’ll take some time to process it all. My initial reaction is that a “strong type-alias” feature might help. If one could write (strawman syntax):<div><br></div><div><font face="monospace, monospace">strong typealias Dog = PyVal    // A semantically independent new type</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">extension Dog {</font></div><div><font face="monospace, monospace">    // Declarations here are only available on “Dog”, not on “PyVal”</font></div><div><font face="monospace, monospace">}</font></div><div><br></div><div>then most of the overload issues would evaporate.</div><div><br></div><div>Nevin</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jan 4, 2018 at 3:52 PM, Chris Lattner via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Hi everyone,<div><br></div><div>With the holidays and many other things behind us, the core team had a chance to talk about python interop + the dynamic member lookup proposal recently.</div><div><br></div><div>Here’s where things stand: we specifically discussed whether a counter-proposal of using “automatically generated wrappers” or “foreign classes” to solve the problem would be better.  After discussion, the conclusion is no: the best approach appears to be DynamicMemberLookup/<wbr>DynamicCallable or something similar in spirit to them.  As such, I’ll be dusting off the proposal and we’ll eventually run it.</div><div><br></div><div>For transparency, I’m attaching the analysis below of what a wrapper facility could look like, and why it doesn’t work very well for Python interop.  I appologize in advance that this is sort of train-of-thought and not a well written doc.  </div><div><br></div><div>That said, it would be really great to get tighter integration between Swift and SwiftPM for other purposes!  I don’t have time to push this forward in the short term though, but if someone was interested in pushing it forward, many people would love to see it discussed seriously.</div><div><br></div><div>-Chris</div><div><br></div><div><br></div><div><div><b>A Swift automatic wrapper facility:</b></div><div><b><br></b></div><div>Requirements:</div><div> - We want the be able to run a user defined script to generate wrappers.</div><div> - This script can have arbitrary dependencies and should get updated when one of them change.</div><div> - These dependencies won’t be visible to the Xcode build system, so the compiler will have to manage them.</div><div> - In principle, one set of wrappers should be able to depend on another set, and wants “overlays”, so we need a pretty general model.</div><div><br></div><div>I don’t think the clang modules based approach is a good way to go.</div><div><br></div><div><br></div><div><b>Proposed Approach: Tighter integration between SwiftPM and Swift</b></div><div><br></div><div>The model is that you should be able to say (strawman syntax):</div><div><br></div><div>   import Foo from <a href="http://github.com/whatever/mypackage" target="_blank">http://github.com/<wbr>whatever/mypackage</a></div><div><div>   import Bar from <a>file:///some/path/on/my/<wbr>machine</a></div></div><div><br></div><div>and have the compiler ask SwiftPM to build and cache the specified module onto your local disk, then have the compiler load it like any other module.  This means that “generated wrappers” is now a SwiftPM/llbuild feature, and we can use the SwiftPM “language” to describe things like:</div><div><br></div><div><div>1. Information about what command line invocation is required to generate the wrappers.</div><div>2. Dependency information so that the compiler can regenerate the wrappers when they are out of date.</div><div>3. Platform abstraction tools since things are in different locations on linux vs mac, Python 2 vs Python 3 is also something that would have to be handled somehow.</div><div>4. The directory could contain manually written .swift code, serving the function similar to “overlays” to augment the automatic wrappers generated.</div><div><br></div><div>We care about Playgrounds and the REPL, and they should be able to work with this model.</div><div><br></div></div><div>I think that this would be a very nice and useful feature.  </div><div><br></div><div><br></div><div><b>Using Wrappers to implement Python Interop:</b></div><div><br></div><div>While such a thing would be generally useful, it is important to explore how well this will work to solve the actual problem at hand, since this is being pitched as an alternative to DynamicMemberLookup.  Here is the example from the list:</div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><pre class="m_7840605251117651583ex" style="margin-top:1.3em;margin-bottom:1.3em;color:rgb(60,60,60);padding:0.9em;background-color:rgb(238,238,238);border:1px solid rgb(221,221,221);font-size:13.0321px;font-variant-ligatures:normal;font-family:&#39;Bitstream Vera Sans Mono&#39;,&#39;DejaVu Sans Mono&#39;,Monaco,Courier,monospace!important"><span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">class</span> BankAccount:
    <span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">def</span> __init__<span class="m_7840605251117651583hili" style="background-color:rgb(223,223,223)">(self, initial_balance: <span class="m_7840605251117651583pr" style="color:rgb(92,92,160)">int</span> = 0) -&gt; None</span>:
        self.balance = initial_balance
    <span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">def</span> deposit<span class="m_7840605251117651583hili" style="background-color:rgb(223,223,223)">(self, amount: <span class="m_7840605251117651583pr" style="color:rgb(92,92,160)">int</span>) -&gt; None</span>:
        self.balance += amount
    <span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">def</span> withdraw<span class="m_7840605251117651583hili" style="background-color:rgb(223,223,223)">(self, amount: <span class="m_7840605251117651583pr" style="color:rgb(92,92,160)">int</span>) -&gt; None</span>:
        self.balance -= amount
    <span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">def</span> overdrawn<span class="m_7840605251117651583hili" style="background-color:rgb(223,223,223)">(self) -&gt; <span class="m_7840605251117651583pr" style="color:rgb(92,92,160)">bool</span></span>:
        <span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">return</span> self.balance &lt; 0

my_account = BankAccount(15)
my_account.withdraw(5)
<span class="m_7840605251117651583pr" style="color:rgb(92,92,160)">print</span>(my_account.balance)</pre></div></div></div></div></blockquote></div><div><br></div><div>The idea is to generate a wrapper like this (potentially including the type annotations as a refinement):</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">typealias</span> BankAccount = <span style="color:rgb(112,61,170)">PyVal</span></div></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0);background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">extension</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(112,61,170)">PyVal</span><span style="color:rgb(0,0,0)"> { </span>// methods on BankAccount</div></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">init</span>(initial_balance: <span style="color:rgb(112,61,170)">PyVal</span>) { … }</div></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">func</span> deposit(amount: <span style="color:rgb(112,61,170)">PyVal</span>) -&gt; <span style="color:rgb(112,61,170)">PyVal</span> { … }</div></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">func</span> withdraw(amount: <span style="color:rgb(112,61,170)">PyVal</span>) -&gt; <span style="color:rgb(112,61,170)">PyVal</span> { … }</div></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">func</span> overdrawn() -&gt; <span style="color:rgb(112,61,170)">PyVal</span> { … }</div></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div></div><div><br></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">my_account = BankAccount(initial_balance: <span style="color:rgb(39,42,216)">1<wbr>5</span>)</div></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">my_account.withdraw(amount: <span style="color:rgb(39,42,216)">5</span>)</div></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">print(my_account.balance)</div></div></blockquote><div><div><br></div></div><div><br></div><div>It is worth pointing out that this approach is very analogous to the “type providers” feature that Joe pushed hard for months ago, it is just a different implementation approach.  The proposal specifically explains why this isn’t a great solution here:</div><div><a href="https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#introduce-f-style-type-providers-into-swift" target="_blank">https://gist.github.com/<wbr>lattner/<wbr>b016e1cf86c43732c8d82f90e5ae54<wbr>38#introduce-f-style-type-<wbr>providers-into-swift</a></div><div><br></div><div>That said, while there are similarities, there are also differences with type providers.  Here are the problems that I foresee:</div><div><br></div><div><br></div><div><div><b>1) This design still requires DynamicMemberLookup</b></div><div><br></div><div>This is because Python doesn’t have property declarations for the wrapper generator to process.  The code above shows this on the last line: since there is no definition of the “balance&quot; property, there will be no “balance member” declared in the PyVal extension.  A wrapper generator can generate a decl for something it can’t “see”.  You can see this in a simpler example:</div><div><br></div><div><div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><pre class="m_7840605251117651583lang-py m_7840605251117651583prettyprint m_7840605251117651583prettyprinted" style="margin-top:0px;margin-bottom:1em;padding:5px;border:0px;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:13px;line-height:inherit;font-family:Consolas,Menlo,Monaco,&#39;Lucida Console&#39;,&#39;Liberation Mono&#39;,&#39;DejaVu Sans Mono&#39;,&#39;Bitstream Vera Sans Mono&#39;,&#39;Courier New&#39;,monospace,sans-serif;vertical-align:baseline;width:auto;max-height:600px;overflow:auto;background-color:rgb(239,240,241);color:rgb(57,51,24);word-wrap:normal"><code style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;line-height:inherit;font-family:Consolas,Menlo,Monaco,&#39;Lucida Console&#39;,&#39;Liberation Mono&#39;,&#39;DejaVu Sans Mono&#39;,&#39;Bitstream Vera Sans Mono&#39;,&#39;Courier New&#39;,monospace,sans-serif;vertical-align:baseline;white-space:inherit"><span class="m_7840605251117651583kwd" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(16,16,148)">class</span><span class="m_7840605251117651583pln" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)"> </span><span class="m_7840605251117651583typ" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(43,145,175)">Car</span><span class="m_7840605251117651583pun" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">(</span><span class="m_7840605251117651583pln" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">object</span><span class="m_7840605251117651583pun" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">):</span><span class="m_7840605251117651583pln" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">
    </span><span class="m_7840605251117651583kwd" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(16,16,148)">def</span><span class="m_7840605251117651583pln" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)"> __init__</span><span class="m_7840605251117651583pun" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">(</span><span class="m_7840605251117651583pln" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">self</span><span class="m_7840605251117651583pun" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">):</span><span class="m_7840605251117651583pln" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">
        self</span><span class="m_7840605251117651583pun" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">.</span><span class="m_7840605251117651583pln" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">speed </span><span class="m_7840605251117651583pun" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)">=</span><span class="m_7840605251117651583pln" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(48,51,54)"> </span><span class="m_7840605251117651583lit" style="margin:0px;padding:0px;border:0px;font-style:inherit;font-variant-ligatures:inherit;font-variant-caps:inherit;font-variant-numeric:inherit;font-variant-alternates:inherit;font-variant-east-asian:inherit;font-stretch:inherit;font-size:inherit;line-height:inherit;font-family:inherit;vertical-align:baseline;color:rgb(125,39,39)">100</span></code></pre></div></div></div></blockquote></div></div></div></div></div><div><br></div><div>We really do want code like this to work:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">let</span> mini = <span>C</span>ar()</div></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">print(<span style="color:rgb(79,129,135)">mini</span>.speed)</div></div></blockquote><div><br></div><div>How will the wrapper generator produce a decl for ‘speed’ when no decl exists?  Doug agreed through offline email that &quot;we’d need to fall back to foo[dynamicMember: “speed”] or something like DynamicMemberLookup.” to handle properties.</div><div><br></div><div><br></div><div><b>2) </b><b>Dumping properties and methods into the same scope won’t work</b></div><div><br></div><div>I didn’t expect this, and I’m not sure how this works, but apparently we accept this:</div><div><br></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162);background-color:rgb(255,255,255)">struct<span style="color:rgb(0,0,0)"> S {</span></div></div></div><div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">var</span> x: <span style="color:rgb(112,61,170)">Int</span></div></div></div><div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">func</span> x(<span style="color:rgb(186,45,162)">_</span> a: <span style="color:rgb(112,61,170)">Int</span>) -&gt; <span style="color:rgb(112,61,170)">Int</span> { <span style="color:rgb(186,45,162)">return</span> a }</div></div></div><div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div></div></div></blockquote><div><div><div><br></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162);background-color:rgb(255,255,255)"><div style="margin:0px;line-height:normal"><span>let</span> x = <span style="color:rgb(79,129,135)">S</span>(x: <span style="color:rgb(39,42,216)">1</span>)</div></div></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162);background-color:rgb(255,255,255)"><div style="margin:0px;line-height:normal;color:rgb(79,129,135)">x<span>.</span>x        // returns 1, not a curried method.  Bug or feature?</div></div></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162);background-color:rgb(255,255,255)"><div style="margin:0px;line-height:normal"><span style="color:rgb(79,129,135)">x</span>.<span style="color:rgb(49,89,93)">x</span>(<span style="color:rgb(39,42,216)">42</span>)    // returns 42</div></div></div></blockquote><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162);background-color:rgb(255,255,255)"><blockquote style="font-family:Helvetica;font-size:12px;margin:0px 0px 0px 40px;border:none;padding:0px"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><div style="margin:0px;line-height:normal"><br></div></div></blockquote></div></div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px">That said, we reject this:</div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><span style="color:rgb(186,45,162);font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)">struct</span><span style="font-family:Menlo;font-size:11px"> S {<br></span><span style="font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)">  </span><span style="font-family:Menlo;font-size:11px;color:rgb(186,45,162)">var</span><span style="font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)"> x: </span><span style="font-family:Menlo;font-size:11px;color:rgb(112,61,170)">Int</span><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><div style="margin:0px;line-height:normal">  <span style="color:rgb(186,45,162)">func</span> x() -&gt; <span style="color:rgb(112,61,170)">Int</span> { <font color="#ba2da2">...</font> }  // invalid redeclaration of x</div></div></div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)"><div style="margin:0px;line-height:normal">}</div></div></div></blockquote><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)"></div></div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px">which means that we’re going to have problems if we find a way to generate property decls (e.g. in response to @property in Python).</div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><br></div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px">Even if we didn’t, we’d still have a problem if we wanted to incorporate types because we reject this:</div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)">struct<span> S {</span></div></div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">  <span style="color:rgb(186,45,162)">var</span> x: <span style="color:rgb(112,61,170)">Int</span></div></div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">  <span style="color:rgb(186,45,162)">var</span> <span>x</span>: <span style="color:rgb(112,61,170)">Float  // invalid redeclaration of X.</span></div></div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><span style="font-family:Menlo;font-size:11px">}</span></div></blockquote><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><br></div><div>This means that even if we have property declarations (e.g. due to use of the Python @property marker for computed properties) we cannot actually incorporate type information into the synthesized header, because multiple classes have all their members munged together and will conflict.</div><div><br></div><div>Further, types in methods can lead to ambiguities too in some cases, e.g. if you have:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><span style="color:rgb(186,45,162);font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)">extension</span><span style="font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)"> PyVal {    // Class Dog</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">func</span> f(a: <span style="color:rgb(112,61,170)">Float</span>) -&gt; <span style="color:rgb(112,61,170)">Float</span> { <font color="#ba2da2">...</font> }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div><span style="color:rgb(186,45,162);font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)">extension</span><span style="font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)"> PyVal {    // Class Cat</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">func</span> f(a: <span style="color:rgb(112,61,170)">Int</span>) {}</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div style="margin:0px;line-height:normal;background-color:rgb(255,255,255);min-height:14px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(62,30,129)">print</span>(<font color="#4f8187">myDog</font>.<span style="color:rgb(49,89,93)">f</span>(a: <span style="color:rgb(39,42,216)">1</span>))</div></blockquote><div><br></div><div>This compiles just fine, but prints out “()&quot; instead of the result of your Dog method, because we select the second overload.  In other cases, I suspect you’d fail to compile due to ambiguities.  This is a case where types are really harmful for Python, and one of the reasons that the Python types do not affect runtime behavior at all.</div><div><div style="color:rgb(186,45,162);font-family:Menlo;font-size:11px;background-color:rgb(255,255,255)"><blockquote style="font-family:Helvetica;font-size:12px;margin:0px 0px 0px 40px;border:none;padding:0px"><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><div style="margin:0px;line-height:normal;color:rgb(79,129,135)"><br></div></div></blockquote></div></div><div><b>3) It’s unclear how to incorporate initializers into this model.</b></div><div><br></div><div>The example above included this as suggested.  It looks nice on the surface, but presents some problems:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">typealias</span> BankAccount = <span style="color:rgb(112,61,170)">PyVal</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0);background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">extension</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(112,61,170)">PyVal</span><span style="color:rgb(0,0,0)"> { </span>// methods on BankAccount</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">init</span>(initial_balance: <span style="color:rgb(112,61,170)">Int</span>) { … }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div><br></div></div></blockquote><div>This has a couple of problems.  First of all, in Python classes are themselves callable values, and this break that.  Second this mooshes all of the initializers for all of the Python classes onto PyVal.</div><div><br></div><div>While it might seem that this would make code completion for initializers ugly, this isn’t actually a problem.  After all, we’re enhancing code completion to know about PyVal already, so we can clearly use this trivial local information to filter the list down.</div><div><br></div><div>The actual problem is that multiple Python classes can have the same initializer, and we have no way to set the ‘self’ correctly in this case.  Consider:</div><div><br></div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><pre class="m_7840605251117651583ex" style="margin-top:1.3em;margin-bottom:1.3em;color:rgb(60,60,60);padding:0.9em;background-color:rgb(238,238,238);border:1px solid rgb(221,221,221);font-size:13.0321px;font-variant-ligatures:normal;font-family:&#39;Bitstream Vera Sans Mono&#39;,&#39;DejaVu Sans Mono&#39;,Monaco,Courier,monospace!important"><span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">class</span> BankAccount:
    <span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">def</span> __init__<span class="m_7840605251117651583hili" style="background-color:rgb(223,223,223)">(self, initial_balance: <span class="m_7840605251117651583pr" style="color:rgb(92,92,160)">int</span> = 0) -&gt; None</span>: …</pre></div></div></div></div></blockquote><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><pre class="m_7840605251117651583ex" style="margin-top:1.3em;margin-bottom:1.3em;color:rgb(60,60,60);padding:0.9em;background-color:rgb(238,238,238);border:1px solid rgb(221,221,221);font-size:13.0321px;font-variant-ligatures:normal;font-family:&#39;Bitstream Vera Sans Mono&#39;,&#39;DejaVu Sans Mono&#39;,Monaco,Courier,monospace!important"><span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">class</span> Gyroscope:
    <span class="m_7840605251117651583kw" style="color:rgb(92,92,160)">def</span> __init__<span class="m_7840605251117651583hili" style="background-color:rgb(223,223,223)">(self, initial_balance: <span class="m_7840605251117651583pr" style="color:rgb(92,92,160)">int</span> = 0) -&gt; None</span>: …</pre></div></div></div></div></blockquote><div>These will require generating one extension:</div><div><br></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0);background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">extension</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(112,61,170)">PyVal</span><span style="color:rgb(0,0,0)"> { </span>// methods on BankAccount</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">init</span>(initial_balance: <span style="color:rgb(112,61,170)">Int</span>) {</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0);background-color:rgb(255,255,255)"><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(186,45,162)">self</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(186,45,162)">init</span><span style="color:rgb(0,0,0)">( </span>/* what Python class do we allocate and pass here?  BankAccount or Gyroscope? */<span style="color:rgb(0,0,0)"> )</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><br></div></div></blockquote><div>I can think of a couple of solutions to this problem, I’d appreciate suggestions for other ones:</div><div><br></div><div><b>3A) Classes turn into typealiases, initializers get name mangled:</b></div><div><br></div><div>something like:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">typealias</span> BankAccount = <span style="color:rgb(112,61,170)">PyVal</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162);background-color:rgb(255,255,255)">extension<span style="color:rgb(0,0,0)"> </span><span style="color:rgb(112,61,170)">PyVal</span><span style="color:rgb(0,0,0)"> {</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">init</span>(BankAccount_initial_<wbr>balance: <span style="color:rgb(112,61,170)">PyVal</span>) { … }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">...</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">let</span> my_account = BankAccount(BankAccount_<wbr>initial_balance: <span style="color:rgb(39,42,216)">15</span>)</div><div><br></div></div></blockquote><div>I don’t like this: this is ugly for clients, and BankAccount is still itself not a value.</div><div><br></div><div><br></div><div><b>3B) Classes turn into global functions:</b></div><div><br></div><div>something like:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">func</span> BankAccount(initial_<wbr>balance: <span style="color:rgb(112,61,170)">PyVal</span>) -&gt; <span style="color:rgb(112,61,170)">PyVal</span> {… }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">...</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">let</span> my_account = BankAccount(initial_balance: <span style="color:rgb(39,42,216)">1<wbr>5</span>)</div><div><br></div></div></blockquote><div>This makes the common cases work, but breaks currying and just seems weird to me.  Maybe this is ok?  This also opens the door for:</div><div><br></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><span style="font-family:Menlo;font-size:11px;background-color:rgb(255,255,255);color:rgb(0,132,0)">// type annotation for clarity only.</span></div></div></blockquote><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">let</span> BankAccount: <span style="color:rgb(112,61,170)">PyVal</span> = BankingModule.BankAccount </div><div><span style="color:rgb(0,132,0)"><br></span></div></blockquote><div>which makes “BankAccount” itself be a value (looked up somehow on the module it is defined in).  </div><div><br></div><div><b>3C) Classes turn into types that are callable with subscripts?</b></div><div><br></div><div>We don’t actually support static subscripts right now (seems like a silly limitation…):</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">struct</span> BankAccount {</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0);background-color:rgb(255,255,255)"><span style="color:rgb(0,0,0)">  </span>// error, subscripts can’t be static.</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">static</span> <span style="color:rgb(186,45,162)">subscript</span>(initial_<wbr>balance initial_balance: <span style="color:rgb(112,61,170)">PyVal</span>) -&gt; <span style="color:rgb(112,61,170)">PyVal</span> { … }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">…</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">let</span> my_account = BankAccount[initial_balance: <span style="color:rgb(39,42,216)">1<wbr>5</span>]</div><div><br></div></div></blockquote><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><br></blockquote></div><div>But we could emulate them with:</div><div><br></div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">struct</span> BankAccountType {</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">subscript</span>(initial_balance initial_balance: <span style="color:rgb(112,61,170)">PyVal</span>) -&gt; <span style="color:rgb(112,61,170)">PyVal</span> { … }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">var</span> BankAccount: <span style="color:rgb(112,61,170)">BankAccountTy<wbr>pe</span> { <span style="color:rgb(186,45,162)">return</span> BankAccountType() }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">…</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">let</span> my_account = BankAccount[initial_balance: <span style="color:rgb(39,42,216)">1<wbr>5</span>]</div><div><br></div></div></blockquote><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote></div></div><div><br></div><div>this could work, but the square brackets are “gross”, and BankAccount is not a useful Python metatype.  We could improve the call-side syntax by introducing a “call decl” or a new “operator()” language feature like:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(112,61,170);background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">extension</span><span style="color:rgb(0,0,0)"> </span>BankAccountType<span style="color:rgb(0,0,0)"> {</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">func</span> () (initial_balance: PyVal) -&gt; PyVal { … }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">var</span> BankAccount: <span style="color:rgb(112,61,170)">BankAccountTy<wbr>pe</span> { <span style="color:rgb(186,45,162)">return</span> BankAccountType() }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">…</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><span style="color:rgb(186,45,162)">let</span> my_account = BankAccount(initial_balance: <span style="color:rgb(39,42,216)">1<wbr>5</span>)</div><div><br></div></div></blockquote><div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"></blockquote></div></div><div><br></div><div>but this still doesn’t solve the “BankAccount as a python value” problem.</div><div><br></div><div><b>4) Throwing / Failability of APIs</b></div><div><br></div><div>Python, like many languages, doesn’t require you to specify whether APIs can throw or not, and because it is dynamically typed, member lookup itself is failable.  That said, just like in C++, it is pretty uncommon for exceptions to be thrown from APIs, and our Error Handling design wants Swift programmers to think about error handling, not just slap try on everything.</div><div><br></div><div>The Python interop prototype handles this by doing this:</div><div><br></div><div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162);background-color:rgb(255,255,255)">extension<span style="color:rgb(0,0,0)"> </span><span style="color:rgb(112,61,170)">PyVal</span><span style="color:rgb(0,0,0)"> {</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0);background-color:rgb(255,255,255)"><span style="color:rgb(0,0,0)">  </span>/// Return a version of this value that may be called.  It throws a Swift</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0);background-color:rgb(255,255,255)"><span style="color:rgb(0,0,0)">  </span>/// error if the underlying Python function throws a Python exception.</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  <span style="color:rgb(186,45,162)">public</span> <span style="color:rgb(186,45,162)">var</span> throwing : <span style="color:rgb(112,61,170)">ThrowingPyVal</span> {</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">    <span style="color:rgb(186,45,162)">return</span> ThrowingPyVal(<span style="color:rgb(186,45,162)">self</span>)</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">  }</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)">}</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><br></div><div style="margin:0px;font-stretch:normal;line-height:normal">.. and both PyVal and ThrowingPyVal are callable.  The implementation of DynamicCallable on ThrowingPyVal throws a Swift error but the implementation on PyVal does not (similar mechanic exists for DynamicMemberLookup).</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><br></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;background-color:rgb(255,255,255)"><div style="font-family:Helvetica;font-size:12px">This leads to a nice model: the PyVal currency type never throws a Swift error (it aborts on exception) so users don’t have to use “try” on everything.  However, if they *want* to process an error, they can. Here is an example from the tutorial:</div><div style="font-family:Helvetica;font-size:12px"><br></div><div style="font-family:Helvetica;font-size:12px"><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)">do<span style="color:rgb(0,0,0)"> {</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(0,0,0)">  </span><span style="color:rgb(186,45,162)">let</span><span style="color:rgb(0,0,0)"> x = </span><span style="color:rgb(186,45,162)"><b>try</b></span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(79,129,135)">Python</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(79,129,135)">open</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(79,129,135)">throwing</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(209,47,27)">&quot;/<wbr>file/that/doesnt/exist&quot;</span><span style="color:rgb(0,0,0)">)</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(62,30,129)"><span style="color:rgb(0,0,0)">  </span>print<span style="color:rgb(0,0,0)">(x)</span></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo">} <span style="color:rgb(186,45,162)">catch</span> <span style="color:rgb(186,45,162)">let</span> err {</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(209,47,27)"><span style="color:rgb(0,0,0)">  </span><span style="color:rgb(62,30,129)">print</span><span style="color:rgb(0,0,0)">(</span>&quot;file not found, just like we expected!&quot;<span style="color:rgb(0,0,0)">)</span></div><div style="margin:0px;font-stretch:normal;line-height:normal;min-height:14px"><br></div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(0,0,0)">  </span>// Here is the error we got:</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo">  <span style="color:rgb(62,30,129)">print</span>(err)</div><div style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo">}</div></div><div style="font-family:Helvetica;font-size:12px"><br></div><div style="font-family:Helvetica;font-size:12px">In practice, this works really nicely with the way that “try” is required for throwing values, but produces a warning when you use it unnecessarily.</div><div style="font-family:Helvetica;font-size:12px"><br></div><div style="font-family:Helvetica;font-size:12px">Coming back to wrappers, it isn’t clear how to handle this: a direct port of this would require synthesizing all members onto both PyVal and ThrowingPyVal.  This causes tons of bloat and undermines the goal of making the generated header nice.</div><span class="HOEnZb"><font color="#888888"><div style="font-family:Helvetica;font-size:12px"><br></div></font></span></div></div><span class="HOEnZb"><font color="#888888"><div>-Chris</div><div><br></div></font></span></div></div><div><br></div></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div>