<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div>While I like the idea of a default value I don't think that you need one as often.</div><div><br></div><div><br></div><div>On another thread ("Optional safe subscripting for arrays") something similar is being discussed where</div><div><br></div><div>array[safe: 6]</div><div><br></div><div>returns Optionals and your proposal is very similar to</div><div><br></div><div><span style="background-color: rgba(255, 255, 255, 0);">array[safe: 6] ?? defaultValue</span></div><div>// or probably rewriting this to</div><div>array[6, default: defaultValue]</div><div><br></div><div>So these two proposals/threads could be merged.</div><div><br></div><div><br></div><div>In case of (Python like) slices I'm not sure whether the additional syntax pays off for its use.</div><div><br></div><div><br></div><div>Do you have any concrete plan how it could be implemented? As additional property/closure/DefaultProtocol?</div><div>I'm in favor of a closure: () -&gt; Element</div><div>since it is like a generator where less weird behaviors can occur due to referencing classes. (Value types would work (almost) flawlessly with a stored property)</div><div><br></div><div><br></div><div>Another note: Could there be a more general way to use "_" as a language feature? So the proposal would be more likely to be accepted.</div><div><br></div><div><br></div><div>Best regards</div><div>- Maximilian</div><div><br>Am 17.01.2016 um 00:37 schrieb Paul Ossenbruggen via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt;:<br><br></div><blockquote type="cite"><div><div class="">This is a preliminary draft,&nbsp;looking for feedback, thanks.&nbsp;</div><div class=""><b style="font-size: 14px;" class=""><br class=""></b></div><b style="font-size: 14px;" class="">Introduction</b><br style="font-size: 14px;" class=""><br class="">There are many cases where you don’t want to deal with an out of range lookup in a array or dictionary. There is quite a lot of boilerplate code to check the range and return a value. This proposal addresses that by making a concise way of providing a default value in an array or dictionary. You quickly and safely want to get the value from an array or dictionary but not have to write a bunch of checks.&nbsp;<div class=""><br class="">Swift-evolution thread: derived&nbsp;from ternary discussion.&nbsp;<br class=""><br class=""><b style="font-size: 14px;" class="">Motivation</b></div><div class=""><b class=""><br class=""></b>There are many times when you want to map value to another, the range of input values is beyond the array index. Typically you have to write code like this;</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><font color="#7b219f" class="">let</font> dayString = [<font color="#b51a00" class="">“Sunday”</font>,&nbsp;<font color="#b51a00" class="">“Monday”,</font>&nbsp;“<font color="#b51a00" class="">Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”</font>]</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#9929bd" class="">guard</font>&nbsp;&nbsp;dayIndex&nbsp;&gt; 0 &amp;&amp;&nbsp;dayIndex&nbsp;&lt; col..count else {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span><font color="#9929bd" class="">return</font><font color="#ff4013" class=""> “invalid day"</font></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;dayString[dayIndex]&nbsp;</div><div class=""><br class=""></div><div class="">Or for a dictionary:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span style="color: rgb(123, 33, 159);" class="">let</span>&nbsp;chineseNumber = [ &nbsp;&nbsp;“<font color="#d12f1b" face="PingFang SC" class="">一” :&nbsp;“One”,</font>&nbsp;</div><div class=""><font color="#b51a00" class=""><span class="" style="font-family: Menlo; color: rgb(209, 47, 27);"><span class="Apple-tab-span" style="white-space:pre">                </span>&nbsp; &nbsp; &nbsp;“</span><span class="" style="line-height: normal; font-family: 'PingFang SC'; color: rgb(209, 47, 27);">二</span>” : ”Two”,</font></div><div class=""><span class="Apple-tab-span" style="white-space:pre">                                        </span>&nbsp; &nbsp; &nbsp;&nbsp;“<font color="#b51a00" class=""><span style="color: rgb(209, 47, 27); font-family: 'PingFang SC';" class="">三</span>” : ”Three”</font>]</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span style="color: rgb(153, 41, 189);" class="">guard</span>&nbsp;&nbsp;<span style="color: rgb(123, 33, 159);" class="">let</span>&nbsp;englishString = englishString <font color="#61177c" class="">else</font> {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span><span style="color: rgb(153, 41, 189);" class="">return</span>&nbsp;“out of range"</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span style="color: rgb(153, 41, 189);" class="">return</span>&nbsp;englishString&nbsp;</div><div class=""><br class=""></div></div><div class="">Currently dictionaries only produce “nil” if not found so you must handle an optional.&nbsp;</div><div class=""><br class=""><b style="font-size: 14px;" class="">Proposed solution:</b></div><div class=""><b style="font-size: 14px;" class=""><br class=""></b></div><div class="">There&nbsp;approach is to add default to the containers.&nbsp;</div><div style="font-size: 15px;" class=""><br class=""></div><div class=""><b class="">Array:</b></div><div class="">There is a new syntax which, allows you to choose a default:</div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><br class=""></div><div class=""><div class=""><span style="color: rgb(123, 33, 159);" class="">let</span>&nbsp;lookupDayOfWeek = [<font color="#b51a00" class="">“Sunday”</font>,&nbsp;<font color="#b51a00" class="">“Monday”,</font>&nbsp;“<font color="#b51a00" class="">Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday” &lt;&gt;</font><font class="">&nbsp;</font><font color="#b51a00" class="">“Invalid Day”&nbsp;</font>]</div></div><div class=""><div class=""><br class=""></div></div><div class=""><div class="">lookupDayOfWeek[1] -&gt; “Monday”</div></div><div class=""><div class="">lookupDayOfWeek[9] -&gt; “Invalid Day”</div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">The&nbsp;<span style="color: rgb(181, 26, 0);" class="">&lt;&gt;</span>&nbsp;which is less than greater than. for the else portion, it indicates outside the range of the array as in less than the minimum index and greater than the highest index. It also looks like a diamond when run together so it stands out to clearly show that it is the default case and won’t be confused with the main array. In all other ways the array behaves the same, if you want to get the default value you could do this:</div><div class=""><br class=""></div><div class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class="">lookupDayOfWeek[ _ ] -&gt; “Invalid Day”</blockquote><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><br class=""></blockquote></div></div><div class="">Iterating an array with a default would not include the default:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#61177c" class="">for</font> day <font color="#61177c" class="">in</font> lookupDayOfWeek {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>print(“Day \(day)”)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><br class=""></div><div class="">You would need to do this to get the default (see below for slices):</div><div class=""><div class=""><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span style="color: rgb(97, 23, 124);" class="">for</span>&nbsp;day&nbsp;<span style="color: rgb(97, 23, 124);" class="">in</span>&nbsp;lookupDayOfWeek[:_] {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>print(“Day \(day)”)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div></div><div class=""><br class=""></div><div class="">or this would put the default first:</div><div class=""><br class=""></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span style="color: rgb(97, 23, 124);" class="">for</span>&nbsp;day&nbsp;<span style="color: rgb(97, 23, 124);" class="">in</span>&nbsp;lookupDayOfWeek[_:] {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>print(“Day \(day)”)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div></div></div><div class=""><br class=""></div></div><div class="">Unless there is a better suggestion for this, as this relies on slices.&nbsp;</div><div class=""><br class=""></div><div class="">Likewise contains() and other operations would not include the default as a result. However, if you were to copy an array with a default it would travel with the array:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><span style="color: rgb(123, 33, 159);" class="">let</span>&nbsp;myOtherArray = lookupDayOfWeek<div class="">print(myOtherArray[_]) &nbsp;-&gt; “Invalid Day”</div><div class=""><br class=""></div></blockquote>If we were to adopt slices it would be possible to copy just the main values like this (based upon python slice syntax, speculative because slice syntax is not yet defined. If it is;):<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><span style="color: rgb(123, 33, 159);" class="">let</span>&nbsp;myOtherArray = lookupDayOfWeek[:]</div></div><div class=""><div class="">print(myOtherArray) -&gt; [<font class="">“Sunday”</font>,&nbsp;<font class="">“Monday”,</font>&nbsp;“<font class="">Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”]&nbsp;</font></div></div><div class=""><div class=""><br class=""></div></div><div class=""><div class=""><span style="color: rgb(123, 33, 159);" class="">let</span>&nbsp;myOtherArray = lookupDayOfWeek[:_]</div></div><div class=""><div class=""><div class="">print(myOtherArray -&gt; [<font class="">“Sunday”</font>,&nbsp;<font class="">“Monday”,</font>&nbsp;“<font class="">Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday” &lt;&gt; "I</font>nvalid Day”]</div></div></div></blockquote><div class=""><div class=""><br class=""></div><div class=""><b class="">Dictionary:</b></div><div class="">For a dictionary, we use the _: to indicate none of the above, which is consistent with current dictionary syntax except that it adds the _ case..</div><div class=""><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><span style="color: rgb(123, 33, 159);" class="">let</span>&nbsp;chineseToEnglishNumber = [ &nbsp;&nbsp;“<font color="#d12f1b" face="PingFang SC" class="">一" :&nbsp;“One”,</font>&nbsp;</div></div><div class=""><div class=""><font color="#b51a00" class=""><span class="" style="font-family: Menlo; color: rgb(209, 47, 27);"><span class="Apple-tab-span" style="white-space: pre;">                </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;“</span><span class="" style="line-height: normal; font-family: 'PingFang SC'; color: rgb(209, 47, 27);">二"</span>: ”Two”,</font></div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                                </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "<font color="#b51a00" class=""><span style="color: rgb(209, 47, 27); font-family: 'PingFang SC';" class="">三"</span>: ”Three”,</font></div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                                </span>&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _:&nbsp; “<font color="#e32400" class="">Out of Range</font>”&nbsp;]</div></div><div class=""><div class=""><br class=""></div></div><div class=""><div class=""><font class="">print(chineseToEnglishNumber[</font>&nbsp;“<font color="#b51a00" class=""><span style="color: rgb(209, 47, 27); font-family: 'PingFang SC';" class="">三</span>”</font><font class="">]) -&gt; “Three"</font></div></div><div class=""><div class=""><font class="">print(chineseToEnglishNumber[“</font><font color="#d12f1b" face="PingFang SC" class="">四”</font><font face="PingFang SC" class="">])</font><font color="#d12f1b" face="PingFang SC" class="">&nbsp;</font><font face="PingFang SC" class="">-&gt;&nbsp;“Out of Range”</font></div></div><div class=""><div class=""><font face="PingFang SC" class=""><br class=""></font></div></div></blockquote><div class=""><div class=""><font class="">This concisely represents what to do if none of the values are usable. No more if let clauses or guards. Diamond&nbsp;<span style="color: rgb(181, 26, 0);" class="">&lt;&gt;</span>&nbsp;could be supported here too, but that is optional for this proposal. The dictionary would be handled pretty much as it is today but the underscore-colon lets you give a default. Similarly, you can access the default value by doing this.</font></div><div class=""><font class=""><br class=""></font></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class=""><font class=""><font class="">print(chineseToEnglishNumber[_</font><font face="PingFang SC" class="">])</font><font color="#d12f1b" face="PingFang SC" class="">&nbsp;</font><font face="PingFang SC" class="">-&gt;&nbsp;“Out of Range</font></font><font face="PingFang SC" class="">”</font></div></div></div><div class=""><div class=""><div class=""><br class=""></div></div></div><div class=""><div class=""><div class="">print(chineseToEnglishNumber.contains(“None”)) -&gt; would return false.&nbsp;</div></div></div><div class=""><div class=""><div class="">print(chineseToEnglishNumber) -&gt; [<font face="Helvetica Neue" class="">"</font><span style="color: rgb(209, 47, 27); font-family: 'PingFang SC';" class="">一</span><font face="Helvetica Neue" class="">": "2", "</font><span style="color: rgb(209, 47, 27); font-family: 'PingFang SC';" class="">二</span><font face="Helvetica Neue" class="">": "1", "</font><span style="color: rgb(209, 47, 27); font-family: 'PingFang SC';" class="">三</span><font face="Helvetica Neue" class="">":&nbsp;“3”&nbsp;&lt;&gt;&nbsp;“</font>&nbsp;<span style="color: rgb(227, 36, 0);" class="">Out of Range</span><font color="#e32400" class="">”</font><font face="Helvetica Neue" class="">]</font></div></div></div></blockquote><font face="Helvetica Neue" class=""><div class=""><font face="Helvetica Neue" class=""><br class=""></font></div>Copying the dictionary would&nbsp;include the default but&nbsp;</font><span style="font-family: 'Helvetica Neue';" class="">iterating it would not include the&nbsp;default:&nbsp;</span><div class=""><div class=""><font face="Helvetica Neue" class=""><br class=""></font></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><span style="color: rgb(97, 23, 124);" class="">for</span>&nbsp;number&nbsp;<span style="color: rgb(97, 23, 124);" class="">in</span>&nbsp;chineseToEnglishNumber {</div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span></div></div></div><div class=""><div class=""><div class="">}</div></div></div></blockquote><div class=""><br class=""></div>to include it (this may need work):<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><span style="color: rgb(97, 23, 124);" class="">for</span>&nbsp;number&nbsp;<span style="color: rgb(97, 23, 124);" class="">in</span>&nbsp;chineseToEnglishNumber[:_] {</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span></div></div><div class=""><div class="">}</div></div></blockquote><div class=""><br class=""></div>since dictionaries are unordered it will not necessarily be at the end..<div class=""><div class=""><div class=""><div class=""><div class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><br class=""></div></blockquote><div class=""><div class=""><b style="font-size: 14px;" class="">Alternatives considered</b></div><div class=""><br class=""></div><div class=""><b class="">Other operators:</b></div><div class="">Tried single colon and double colon but did not stand out enough and colon might not work if we adopted slices.&nbsp;</div><div class=""><br class=""></div><div class=""><b class="">Sets</b></div><div class="">Thought about sets but not sure that makes sense because you only test existence of a member usually, the following kind makes sense to a point:</div><div class=""><span style="font-family: 'PingFang SC';" class=""><br class=""></span></div></div></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class=""><div class=""><div class=""><span style="font-family: 'PingFang SC';" class="">let set = Set(“A”,&nbsp;“B”,&nbsp;“C” &lt;&gt;&nbsp;“D”)</span></div></div></div></div></div><div class=""><div class=""><font face="PingFang SC" class="">set.contains(“B”) -&gt; true</font></div></div><div class=""><div class=""><div class=""><font face="PingFang SC" class="">set.contains(“D”) -&gt; false</font></div></div></div><div class=""><div class=""><div class=""><font face="PingFang SC" class="">set.contains(“F”) -&gt; false</font></div></div></div><div class=""><div class=""><font face="PingFang SC" class=""><br class=""></font></div></div><div class=""><div class=""><font face="PingFang SC" class="">print(set) -&gt; [“A”,&nbsp;“B”,&nbsp;“C”]</font></div></div><div class=""><div class=""><font face="PingFang SC" class=""><br class=""></font></div></div></blockquote><div class=""><div class=""><font face="PingFang SC" class="">but typically you are just checking for&nbsp;existence or getting all values so having it return a&nbsp;default does not make sense.&nbsp;</font></div><div class=""><font face="PingFang SC" class=""><br class=""></font></div><div class=""><font face="PingFang SC" class=""><b class="">Map</b></font></div><div class="">This came out of the ternary and switch discussions, this could be done with map defaults. If we don’t want to add it to the container types that might be a better way to go. See that thread for more details.&nbsp;</div><div class=""><br class=""></div><div class=""><font face="PingFang SC" class=""><br class=""></font></div><div class=""><br class=""></div></div></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>