<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Jul 13, 2016 at 1:14 PM, Tim Vermeulen via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></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"><div>I thought that was mainly about former proposals in the Github repo, but I’ll gladly bring this up again at a more appropriate time.</div><div><br></div><div>To address your message: I wouldn’t really want guard <condition> else { } to be valid code. The default return value is simply returned if the end of the function body is reached and nothing has been returned yet. guard <condition> else { return } could possibly be allowed in case of a default return value, but definitely not an empty guard body. This wouldn’t cause any problems, would it?</div></div></blockquote><div><br></div><div>This specific idea you're proposing has been brought up on the list previously, I think maybe twice. Visual Basic was mentioned previously, in case that would help you search through list archives. It has not been previously received well, but if after looking through the archives you feel it's still relevant to discuss, I'd also mention that post-Swift 3 would be more appropriate.</div><div><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><div class="h5"><br><div><blockquote type="cite"><div>On 13 Jul 2016, at 17:47, Charlie Monroe <<a href="mailto:charlie@charliemonroe.net" target="_blank">charlie@charliemonroe.net</a>> wrote:</div><br><div><div style="word-wrap:break-word">Hi Tim,<div><br></div><div>the core team asked us to defer any discussion on post-Swift-3 related proposals.</div><div><br></div><div>That said, there have been several discussion around this topic (in the past few months) and I believe the general attitude towards them was negative, due to it leading to statements such as </div><div><br></div><div>guard <condition> else { }</div><div><br></div><div>which</div><div><br></div><div>a) doesn't express what will happen when the condition is not met, making the code hard to read</div><div><br></div><div>b) can lead to bugs in code since the compiler makes sure that the flow doesn't continue beyond the guard statement and with default returns, this would compiler without a warning or an error:</div><div><br></div><div>for obj in array {</div><div><span style="white-space:pre-wrap">        </span>guard obj.meetsConditions() else {</div><div><span style="white-space:pre-wrap">                </span>// Implicit return - most likely not intentional,</div><div><span style="white-space:pre-wrap">                </span>// you most likely want "continue" in here</div><div><span style="white-space:pre-wrap">        </span>}</div><div><br></div><div><span style="white-space:pre-wrap">        </span>// ...</div><div>}</div><div><br></div><div><br><div><div><blockquote type="cite"><div>On Jul 13, 2016, at 4:57 PM, Tim Vermeulen via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br><div><div style="word-wrap:break-word">This idea is purely additive and isn’t to be considered for Swift 3.<div><br></div><div>Oftentimes a function has a very obvious default argument to fall back on. If the return value is optional, this is generally nil. If the return value is Bool, it’s probably `false`. Often this fallback value is returned at the end of the function, just to return something if nothing has been returned yet. For instance, consider this TreeNode class:</div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal"><span style="color:#ba2da2">class</span><span> TreeNode<Element> {</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">var</span><span> value: </span><span style="color:#4f8187">Element</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">var</span><span> children: [</span><span style="color:#4f8187">TreeNode</span><span>]</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">init</span><span>(value: </span><span style="color:#4f8187">Element</span><span>) {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">self</span><span>.</span><span style="color:#4f8187">value</span><span> = value</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#4f8187">children</span><span> = []</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">func</span><span> contains(</span><span style="color:#ba2da2">_</span><span> predicate: (</span><span style="color:#4f8187">Element</span><span>) </span><span style="color:#ba2da2">throws</span><span> -> </span><span style="color:#703daa">Bool</span><span>) </span><span style="color:#ba2da2">rethrows</span><span> -> </span><span style="color:#703daa">Bool</span><span> {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">try</span><span> predicate(</span><span style="color:#4f8187">value</span><span>) {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> </span><span style="color:#ba2da2">true</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">for</span><span> child </span><span style="color:#ba2da2">in</span><span> </span><span style="color:#4f8187">children</span><span> {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">try</span><span> child.</span><span style="color:#31595d">contains</span><span>(predicate) {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> </span><span style="color:#ba2da2">true</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal;color:rgb(186,45,162)"><span> </span><span>return</span><span> </span><span>false </span><span style="color:rgb(0,132,0)">// 1</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">func</span><span> first(</span><span style="color:#ba2da2">where</span><span> predicate: (</span><span style="color:#4f8187">Element</span><span>) </span><span style="color:#ba2da2">throws</span><span> -> </span><span style="color:#703daa">Bool</span><span>) </span><span style="color:#ba2da2">rethrows</span><span> -> </span><span style="color:#4f8187">Element</span><span>? {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">try</span><span> predicate(</span><span style="color:#4f8187">value</span><span>) {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> </span><span style="color:#4f8187">value</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">for</span><span> child </span><span style="color:#ba2da2">in</span><span> </span><span style="color:#4f8187">children</span><span> {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">let</span><span> result = </span><span style="color:#ba2da2">try</span><span> child.</span><span style="color:#31595d">first</span><span>(</span><span style="color:#ba2da2">where</span><span>: predicate) {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> result</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> </span><span style="color:#ba2da2">nil </span><span style="color:rgb(0,132,0)">// 2</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">var</span><span> leftMostDescendant: </span><span style="color:#4f8187">TreeNode</span><span>? {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">let</span><span> child = </span><span style="color:#4f8187">children</span><span>.</span><span style="color:#703daa">first</span><span> {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> child.</span><span style="color:#4f8187">leftMostDescendant</span><span> ?? child</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal"><span><br></span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> </span><span style="color:#ba2da2">nil </span><span style="color:rgb(0,132,0)">// 3</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span>}</span></div></div></div></div><div><br></div><div>These code patterns are quite usual. If we could give default return values to functions, we could get rid of the final `return` statements:</div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><div style="margin:0px;line-height:normal"><span style="color:#ba2da2">func</span><span> contains(</span><span style="color:#ba2da2">_</span><span> predicate: (Element) </span><span style="color:#ba2da2">throws</span><span> -> Bool) </span><span style="color:#ba2da2">rethrows</span><span> -> </span><span style="color:#703daa">Bool</span><span> = </span><span style="color:#ba2da2">false</span><span> {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">try</span><span> predicate(value) {</span></div><div style="margin:0px;line-height:normal;color:rgb(186,45,162)"><span> </span><span>return</span><span> </span><span>true</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">for</span><span> child </span><span style="color:#ba2da2">in</span><span> children {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">try</span><span> child.contains(predicate) {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> </span><span style="color:#ba2da2">true</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal"><span>}</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span></span><br></div><div style="margin:0px;line-height:normal"><span style="color:#ba2da2">func</span><span> first(</span><span style="color:#ba2da2">where</span><span> predicate: (Element) </span><span style="color:#ba2da2">throws</span><span> -> Bool) </span><span style="color:#ba2da2">rethrows</span><span> -> </span><span style="color:#703daa">Element</span><span>? = </span><span style="color:#ba2da2">nil</span><span> {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">try</span><span> predicate(value) {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> value</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span> </span><br></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">for</span><span> child </span><span style="color:#ba2da2">in</span><span> children {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">let</span><span> result = </span><span style="color:#ba2da2">try</span><span> child.first(</span><span style="color:#ba2da2">where</span><span>: predicate) {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> result</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal"><span>}</span></div><div style="margin:0px;line-height:normal;min-height:13px"><span></span><br></div><div style="margin:0px;line-height:normal"><span style="color:#ba2da2">var</span><span> leftMostDescendant: </span><span style="color:#4f8187">TreeNode</span><span>? = </span><span style="color:#ba2da2">nil</span><span> {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">if</span><span> </span><span style="color:#ba2da2">let</span><span> child = children.first {</span></div><div style="margin:0px;line-height:normal"><span> </span><span style="color:#ba2da2">return</span><span> child.leftMostDescendant ?? child</span></div><div style="margin:0px;line-height:normal"><span> }</span></div><div style="margin:0px;line-height:normal"><span>}</span></div></div></div><div><br></div><div>The default return value shouldn’t be part of the function signature (i.e. it shouldn’t appear in interface files) because it’s an implementation detail, but right after the return type is probably the most natural place to put it (similar to default function parameters).</div><div><br></div><div>Let me know what you think.</div></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" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br></div></div></div></div></blockquote></div><br></div></div></div><br>_______________________________________________<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/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div></div>