<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 20, 2017, at 6:07 AM, David Sweeris <<a href="mailto:davesweeris@mac.com" class="">davesweeris@mac.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""><br class=""></div><div class="">On Jan 9, 2017, at 02:13, Charlie Monroe via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div class="">I came across something that I'm not sure it's a bug or by design and if it's by design, whether this should be discussed here.</div><div class=""><br class=""></div><div class="">Example:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">class</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Foo {</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">(number: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class="">) { </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">/* ... */</span><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; min-height: 10px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> closure = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Foo</span><span style="font-variant-ligatures: no-common-ligatures" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">(number:) </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// (Int) -> Foo</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class="">[</span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">1</span><span style="font-variant-ligatures: no-common-ligatures;" class="">, </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">2</span><span style="font-variant-ligatures: no-common-ligatures;" class="">, </span><span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">3</span><span style="font-variant-ligatures: no-common-ligatures;" class="">].</span><span style="font-variant-ligatures: no-common-ligatures; color: #3e1e81" class="">map</span><span style="font-variant-ligatures: no-common-ligatures;" class="">(</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">closure</span><span style="font-variant-ligatures: no-common-ligatures;" class="">) </span><span style="font-variant-ligatures: no-common-ligatures" class="">// [Foo, Foo, Foo]</span></div></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class="">This works great until the initializer gets a default argument:</span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">class</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Foo {</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">(number: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span><span style="font-variant-ligatures: no-common-ligatures" class="">, string: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">String</span><span style="font-variant-ligatures: no-common-ligatures" class=""> = </span><span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">""</span><span style="font-variant-ligatures: no-common-ligatures" class="">) { </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">/* ... */</span><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; min-height: 10px;" class=""><span style="color: rgb(0, 132, 0);" class=""><br class=""></span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; min-height: 10px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><span style="color: rgb(0, 132, 0);" class="">// Error: Foo has no member init(number:)</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> closure = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Foo</span><span style="font-variant-ligatures: no-common-ligatures;" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures;" class="">(number:) </span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><br class=""></span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span style="font-family: Helvetica; font-size: 10px;" class="">I was wondering if we could get closures to methods without the default arguments. Currently, this needs to be worked around by e.g. creating a second closure that invokes the method without the default arguments:</span></span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span style="font-family: Helvetica; font-size: 10px;" class=""><br class=""></span></span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span> closure: (<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>) -> <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Foo</span> = { <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Foo</span>(number: $0) }</span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><br class=""></span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span style="font-family: Helvetica; font-size: 10px;" class="">But to me it seems like something that should work "out of the box".</span></span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span style="font-family: Helvetica; font-size: 10px;" class=""><br class=""></span></span></div><div style="margin: 0px; font-size: 9px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span style="font-family: Helvetica; font-size: 10px;" class="">Thoughts?</span></span></div></span></div></div></blockquote><br class=""><div class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">IIRC, this issue was raised a while ago, and as best as I recall the gist of the answer was that default arguments are implemented at the call site, and because of that you can't pass a function with default arguments to something expecting a function with fewer arguments even though the two calls look identical in the source code.</span></div><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">It causes other issues, too. For instance, if we have</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> protocol Initable { init() }</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">And</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> struct Foo { init(_ x: Int = 0) {} }</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">We're left in an odd situation where `Foo` can't meaningfully conform to `Initable` because while "init(_: Int = 0)" is not the same as "init()", if you add a "init()" to `Foo`</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">you'll get an ambiguous somethingerather error because there's no mechanism for the compiler to know whether you want the actual "0 argument" function or the "1 argument with 1 default value" function.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div></div></div></div></blockquote><div><br class=""></div><div>Sure, but in the case of the closure, it shouldn't be a major issue for the compiler to automatically generate a "proxy" closure that would call the implementation with supplied parameters + rest as default - just like with the current workaround.</div><div><br class=""></div><div>If no one thinks that this is something that needs to go through the evolution process (in case there is e.g. a good reason why this shouldn't work), I'll just file this as a bug/enhancement request at <a href="http://bugs.swift.org" class="">bugs.swift.org</a>. </div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Aside from re-architecting the default argument system (which I'm not even sure is possible, let alone a good idea), I think I see couple ways forward for the protocol conformance issue. Both have downsides, though.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">1) Require any potentially conflicting protocol functions to be in an extension so the compiler knows what's going on, have "Foo()" call the one defined in the type, and use "(Foo as Initable)()" for the protocol version defined in an extension. This could get real confusing real fast if people don't realize there's two functions with, as far as they can tell, the same signature.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">2) Add default argument support to protocols. The syntax that makes sense to me would be something like</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> protocol Bar {</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> func baz(_: Int = _)</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> }</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">On the downside, I suspect this would necessarily add a phantom "Self or associated type requirement" so that the compiler could have a way to get at each implementation's default value. It's not ideal... You'd get an error kinda out of the blue if you tried to use the function non-generically, but at least you couldn't have a function change out from under you.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">- Dave Sweeris </span></div></div></div></div></blockquote></div><br class=""></body></html>