<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Mon, Nov 27, 2017 at 11:12 AM Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On Nov 27, 2017, at 12:50 PM, Douglas Gregor &lt;<a href="mailto:dgregor@apple.com" target="_blank">dgregor@apple.com</a>&gt; wrote:</div><br class="m_-2480070432859288515Apple-interchange-newline"><div><div style="word-wrap:break-word;line-break:after-white-space"><div dir="auto" style="word-wrap:break-word;line-break:after-white-space"><br><div><br><blockquote type="cite"><div>On Nov 24, 2017, at 3:11 PM, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_-2480070432859288515Apple-interchange-newline"><div><div style="word-wrap:break-word"><div>As mentioned in my prior message, I currently have a PR open to update the generics manifesto (<a href="https://github.com/apple/swift/pull/13012" target="_blank">https://github.com/apple/swift/pull/13012</a>).  I removed one topic from that update at Doug Gregor’s request that it be discussed on the list first.  </div><div><br></div><div>The idea is to add the ability to make default arguments conditional (i.e. depend on generic constraints).  It is currently possible to emulate conditional default arguments using an overload set.  This is verbose, especially when several arguments are involved.  Here is an example use case using the overload method to emulate this feature:</div><div><br></div><div>```swift</div><div>protocol Resource {</div><div>  associatedtype Configuration</div><div>  associatedtype Action</div><div>}</div><div>struct ResourceDescription&lt;R: Resource&gt; {</div><div>  func makeResource(with configuration: R.Configuration, actionHandler: @escaping (R.Action) -&gt; Void) -&gt; R {</div><div>    // create a resource using the provided configuration</div><div>    // connect the action handler</div><div>    // return the resource</div><div>  }</div><div>}</div><div><br></div><div>extension ResourceDescription where R.Configuration == Void {</div><div>  func makeResource(actionHandler: @escaping (R.Action) -&gt; Void) -&gt; R {</div><div>    return makeResource(with: (), actionHandler: actionHandler)</div><div>  }</div><div>}</div><div><br></div><div>extension ResourceDescription where R.Action == Never {</div><div>  func makeResource(with configuration: R.Configuration) -&gt; R {</div><div>    return makeResource(with: configuration, actionHandler: { _ in })</div><div>  }</div><div>}</div><div><br></div><div>extension ResourceDescription where R.Configuration == Void, R.Action == Never {</div><div>  func makeResource() -&gt; R {</div><div>    return makeResource(with: (), actionHandler: { _ in })</div><div>  }</div><div>}</div><div><br></div><div>```</div><div><br></div><div>Adding language support for defining these more directly would eliminate a lot of boilerplate and reduce the need for overloads. </div></div></div></blockquote><div><br></div><div>If one could refer to `self` in a default argument (which is not a big problem), you could turn the default into a requirement itself… although it doesn’t *quite* work with your example as written because it would always need to be implemented somehow:</div><div><br></div><div><blockquote type="cite"><div style="word-wrap:break-word;line-break:after-white-space"><div>protocol Resource {</div><div>  associatedtype Configuration</div><div>  associatedtype Action</div></div></blockquote>    func defaultConfiguration() -&gt; Configuration</div><div>    func defaultHandler() -&gt; ((R.Action) -&gt; Void)<br><blockquote type="cite"><div style="word-wrap:break-word;line-break:after-white-space"><div>}</div></div></blockquote></div></div></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>This won’t work on its own for this use case because there is only a valid default in relatively narrow (but common) cases.  For most values of Configuration and Action an argument must be provided by the caller.  Xiaodi’s proposed syntax is the best fit (so far) for the use case I had in mind.  </div></div></div></blockquote><div><br></div><div>Out of curiosity, what part of my proposed syntax misses the mark for your use case?</div><div><br></div><div>The parts that I think are somewhat unfortunate are losing a small bit of reference locality and the introduction of a new operator to distinguish between &quot;default argument not present if no match found&quot; vs. &quot;compile time error&quot;, definitely. However, one unfortunate trend I&#39;ve noticed when new features are proposed is that there&#39;s a tendency to end up with &quot;let&#39;s invent @yet_another_attribute&quot; and that just doesn&#39;t seem scalable or clean if we can strive to better integrate it into the syntax of the language.</div><div><br></div><div>I&#39;m particularly interested in this because I hit a use case that&#39;s similar to yours in my own code base. I wanted a generic type that could be instantiated with a disjoint type set—either a RawRepresentable whose RawValue is Int, or an Int itself. This could have been solved by having Int retroactively conform to RawRepresentable, but doing that to a fundamental built-in type Feels Dirty™, so I made it work by not constraining the generic type at all and moving the public initializers to constrained extensions so that the only way you could *instantiate* the type is if you have a correct type argument, and those initializers pass through to an internal one, sending along a closure that does the correct transformation: <a href="https://github.com/allevato/icu-swift/blob/master/Sources/ICU/RuleBasedBreakCursor.swift#L208">https://github.com/allevato/icu-swift/blob/master/Sources/ICU/RuleBasedBreakCursor.swift#L208</a></div><div><br></div><div>With your proposed addition, I could hoist those closures into default arguments based on the constraints instead of adding extensions.</div><div><br></div><div>That being said, I don&#39;t find the extension-based approach *that* restrictive, and it kind of makes sense from the point of view of &quot;this overload only exists for this type under a particular constraint&quot;. I wonder how often this comes up that combinatorial explosion is truly harmful.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><br></div><div>That said, the ability to refer to self in default arguments is complementary as it would expand the cases where conditional default arguments could be provided.  For example, in the example above it would allow a resource to provide a nontrivial default configuration.</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word;line-break:after-white-space"><div dir="auto" style="word-wrap:break-word;line-break:after-white-space"><div><div><br></div><blockquote type="cite"><div><div style="word-wrap:break-word"><div> Doug mentioned that it may also help simplify associated type inference (<a href="https://github.com/apple/swift/pull/13012#discussion_r152124535" target="_blank">https://github.com/apple/swift/pull/13012#discussion_r152124535</a>).</div></div></div></blockquote><br></div><div>Oh, I thought this was something related to choosing a defaults for associated types, which might have helped with my current associated-type-inference quandary. The topic you actually wanted to discuss is disjoint (sorry).</div></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>I was wondering how it was related and wondered if it was somehow due to reduction in the size of the overload set.  If you have any ideas on changes that might help guide the inference algorithm somehow please start a new thread.  Even if you’re only able to describe the challenges it might be worth a thread if it’s possible others might have useful ideas.  Improving the reliability and predictability of inference is a very important topic!</div><br><blockquote type="cite"><div><div style="word-wrap:break-word;line-break:after-white-space"><div dir="auto" style="word-wrap:break-word;line-break:after-white-space"><div><br></div><div><span class="m_-2480070432859288515Apple-tab-span" style="white-space:pre-wrap">        </span>- Doug</div><div><br></div><br></div></div></div></blockquote></div><br></div>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div>