<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=""><div class="">It’s worth noting that the question of “how do these defaults interact with other defaults” is an issue that has left this feature dead in the water in the Rust language despite being accepted for inclusion two years ago. See <a href="https://internals.rust-lang.org/t/interaction-of-user-defined-and-integral-fallbacks-with-inference/2496" class="">https://internals.rust-lang.org/t/interaction-of-user-defined-and-integral-fallbacks-with-inference/2496</a> for some discussion of the issues at hand.</div><div class=""><br class=""></div><div class="">For those who don’t want to click that link, or are having trouble translating the syntax/terms to Swift. The heart of Niko’s post is the following (note: functions are used here for expedience; you can imagine these are `inits` for a generic type if you wish):</div><div class=""><br class=""></div><div class=""><div class=""><font face="Courier New" class="">// Example 1: user supplied default is IntegerLiteralConvertible</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">func foo<T=Int64>(t: T) { ... }</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">foo<_>(22)</font></div><div class=""><font face="Courier New" class="">// ^</font></div><div class=""><font face="Courier New" class="">// |</font></div><div class=""><font face="Courier New" class="">// What type gets inferred here?</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">// Example 2: user supplied default isn't IntegerLiteralConvertible</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">func bar<T=Character>(t: T) { ... }</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">bar<_>(22)</font></div><div class=""><font face="Courier New" class="">// ^</font></div><div class=""><font face="Courier New" class="">// |</font></div><div class=""><font face="Courier New" class="">// What type gets inferred here?</font></div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">There are 4 strategies:</div><div class=""><br class=""></div><div class="">(Note: I use “integer literal” here for simplicity; in general it's “any kind of literal, and its associated LiteralType”. So this reasoning also applies to FloatLiteralType, StringLiteralType, BooleanLiteralType, etc.)</div><div class=""><div class=""><br class=""></div><div class="">* Unify all: always unify the variables with all defaults. This is the conservative choice in that it gives an error if there is any doubt.</div><div class=""><br class=""></div><div class="">* Prefer literal: always prefer IntegerLiteralType (Int). This is the maximally backwards compatible choice, but I think it leads to very surprising outcomes.</div><div class=""><br class=""></div><div class="">* Prefer user: always the user-defined choice. This is simple from one point of view, but does lead to a potentially counterintuitive result for example 2.</div><div class=""><br class=""></div><div class="">* Do What I Mean (DWIM): Prefer the user-defined default, except in the case where the variable is unified with an integer literal <i class="">and</i> the user-defined default isn't IntegerLiteralConvertible. This is complex to say but leads to sensible results on both examples. (Basically: prefer user, but fallback to IntegerLiteralType if the user default doesn’t actually make sense)</div></div><div class=""><br class=""></div><div class=""><pre style="overflow: auto; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 14px; color: rgb(34, 34, 34);" class=""><code style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 1em; overflow: auto; tab-size: 4; background-color: rgb(248, 248, 248); word-wrap: normal; display: block; padding: 5px 10px; max-height: 500px;" class="">| Strategy | Example 1 | Example 2 |
| -------------- | --------- | --------- |
| Unify all | Error | Error |
| Prefer literal | Int | Int |
| Prefer user | Int64 | Error |
| DWIM | Int64 | Int |</code></pre></div><div class=""><br class=""></div><div class="">Personally, I’ve always favoured DWIM. Especially in Swift where IntegerLiteralType inference is so frequently used (you don’t want adding a default to cause code to stop compiling!). In practice I don’t expect there to be many cases where this ambiguity actually kicks in, as it requires the user-specified default to be a LiteralConvertible type that isn't the relevant LiteralType, and for the type variable to affect an actual Literal. So <T=String>(x: T) never causes problems, but <T=StaticString>(x: T) does.</div><div class=""><br class=""></div><div class="">As for the matter of “what if I want the other one” — you clearly know the actual type you want; just name it explicitly.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 24, 2017, at 2:59 AM, Srđan Rašić via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class="">> If the answer to the above question is "yes, T is inferred as Int" then we need some way to express "give me the default for T, which is Float."</span></div><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class=""><br class=""></span></div><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class="">I don't think that we need that. It would introduce a new level of explicitness, "I want the default, but I don't care what the default is", that is not really useful. If you don't care what the default type is, you probably also don't care that you are defaulting. If you do care what the default type is, you would explicitly sepecify it as `X<Float>`. </span></div><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class=""><br class=""></span></div><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class=""><br class=""></span></div><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class="">> If the answer to the above question is "no" then we need some way to express "don't give me the default; rather, infer type T from the right hand side."</span><br class=""></div><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class=""><br class=""></span></div><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class="">That would be preferred behavior. Infer from the context if possible, use default otherwise. </span></div><div class=""><span style="color:rgb(49,49,49);word-spacing:1px;background-color:rgb(255,255,255)" class=""><br class=""></span></div><div class=""><br class=""><div class="gmail_quote"><div class="">tir. 24. jan. 2017 kl. 05.11 skrev Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>>:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_msg">While it looks nicer without the angle brackets, that suggestion is unresponsive to David's point that we need some way to distinguish defaulted generic arguments from inferred generic arguments.<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Consider:</div><div class="gmail_msg">```</div><div class="gmail_msg">let a: Optional = 1 // Optional<Int></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">enum FloatPreferringOptional<T = Float> {</div><div class="gmail_msg"> case some(T)</div><div class="gmail_msg"> case none</div><div class="gmail_msg">}</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">let b: FloatPreferringOptional = 1</div><div class="gmail_msg">// Does this give you an FloatPreferringOptional<Int>?</div><div class="gmail_msg">```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">If the answer to the above question is "yes, T is inferred as Int" then we need some way to express "give me the default for T, which is Float." If the answer to the above question is "no" then we need some way to express "don't give me the default; rather, infer type T from the right hand side."</div></div><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div></div><div class="gmail_extra gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg">On Mon, Jan 23, 2017 at 6:30 PM, Matthew Johnson via swift-evolution <span class="gmail_msg"><<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br class="gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg">This proposal looks good to me. I have been looking forward to more flexible generic arguments for a while.<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I agree with previous commenters who prefer the option to leave off the angle brackets when all parameters have defaults.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">The proposal specifically mentions that the syntax is inspired by that of function arguments. This is good, but I wonder if maybe we should draw further inspiration from function arguments and also add parameter labels for generic arguments. Both feel like low hanging fruit in the generics area (correct me if I’m wrong about that) and it would be great to see both enhancements make it into Swift 4.</div><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div class="m_-4271769178076865979h5 gmail_msg"><div class="gmail_msg">On Jan 23, 2017, at 9:55 AM, Srđan Rašić via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="gmail_msg m_-4271769178076865979m_-2275226256302434135Apple-interchange-newline"></div></div><div class="gmail_msg"><div class="gmail_msg"><div class="m_-4271769178076865979h5 gmail_msg"><div class="gmail_msg">Hi Everyone,<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I've opened a PR (<a href="https://github.com/apple/swift-evolution/pull/591" class="gmail_msg" target="_blank">https://github.com/apple/swift-evolution/pull/591</a>) proposing default generic arguments which I think would be nice addition to the language. They are also mentioned in "Generic manifesto". </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">The proposal is focusing around generic types. Generic functions are not coved by the proposal and I don't think that we need default generic arguments in generic functions as all the types are always part of the function signature so the compiler can always infer them. One corner case might be if using default argument values in which case support for default generic arguments in functions might be useful.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">It would be great to hear your opinions and suggestions so I can refine the proposal.<br class="gmail_msg"></div></div></div></div><span class="gmail_msg"><br class=""><br class="">_______________________________________________<br class="gmail_msg">swift-evolution mailing list<br class="gmail_msg"><a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg"></span></div></blockquote></div><br class="gmail_msg"></div></div></div><br class="gmail_msg">_______________________________________________<br class="gmail_msg"><br class=""><br class="">swift-evolution mailing list<br class="gmail_msg"><br class=""><br class=""><a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg"><br class=""><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg"><br class=""><br class=""><br class="gmail_msg"></blockquote></div><br class="gmail_msg"></div></div></blockquote></div></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>