<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Aug 15, 2016 at 2:29 PM, Tim Vermeulen <span dir="ltr">&lt;<a href="mailto:tvermeulen@me.com" target="_blank">tvermeulen@me.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><div><div class="h5"><blockquote type="cite"><div>On 15 Aug 2016, at 21:27, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Aug 15, 2016 at 1:57 PM, Haravikk via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On 15 Aug 2016, at 13:44, Tim Vermeulen &lt;<a href="mailto:tvermeulen@me.com" target="_blank">tvermeulen@me.com</a>&gt; wrote:</div><br><div><div><blockquote type="cite"><blockquote type="cite">On 15 Aug 2016, at 08:02, Justin Jia via swift-evolution&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolutio<wbr>n@swift.org</a>(<a href="mailto:swift-evolution@swift.org" target="_blank">mailto:swift-<wbr>evolution@swift.org</a>)&gt;wrote:<br>Hi!<br><br>I don’t know if this has came up before. I tried to search though the mailing list but didn’t find any related threads.<br><br>This is purely a syntactic thing (which I know it’s the lowest priority for Swift 4), but I think it’s an important one.<br><br>Let’s say we have a struct with a function:<br><br>```<br>struct Foo {<br>func bar(x: Int)<br>}<br>```<br><br>We can use optionals:<br><br>```<br>let foo: Foo? = nil<br>let x = 1<br>foo!.bar(x: x) // Able to compile, but will cause runtime error<br>foo?.bar(x: x) // Able to compile, and won&#39;t cause runtime error<br>```<br><br>However:<br><br>```<br>let foo = Foo()<br>let x: Int? = nil<br>foo.bar(x: x!) // Able to compile, but will cause runtime error<br>foo.bar(x: x?) // Won&#39;t compile<br>```<br><br>I propose that we should allow `foo.bar(x: x?)`, which should be equivalent to:<br><br>```<br>if let x = x {<br>foo.bar(x: x)<br>}<br>```<br><br>What do you think?<br></blockquote>I like the intent behind this, but personally I think it&#39;s not clear enough. For me, putting the statement in a conditional as you&#39;ve shown is the better solution, as it&#39;s a lot clearer exactly what&#39;s going on. Putting a question mark on a variable makes it look like something specific to that variable, rather than preventing the entire statement from executing.<br></blockquote><br>I get where you’re coming from, but how would people react if optional chaining wasn’t in the language yet and someone proposed it now? I know it’s not strictly the same thing, but it’s still a single question mark that prevents the whole statement from being executed. I think it would be met with a lot of resistance from people saying that being more explicit with `if let` is the way to go.<br></div></div></blockquote><div><br></div></span><div>True, but with optional chaining the position of the question mark makes it a lot more clear where it stops, whereas in this proposal the question mark seems a bit less intuitive since it&#39;s within the parenthesis yet affecting the statement outside of it.</div><span><br><blockquote type="cite"><div><div><blockquote type="cite">There may be some alternatives though, for example, what about a shorthand for the conditional like so:<br><br>if let x? { foo.bar(x: x) }<br>if x? { foo.bar(x: x) } // even shorter?<br></blockquote><br>The alternatives you’ve come up with would only work if foo.bar doesn’t return anything. If it does return something, and you want to assign it to a variable, you have to declare the variable beforehand and it just becomes ugly. It’s then probably a better idea to use map/flatmap:</div></div></blockquote></span></div><br><div>Hmm, what about something involving the where keyword? Something like:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="Monaco">let value = foo.bar(x: x) where x?</font></div></blockquote><br><div>Some people have queried the ability to use where in assignments before, as another way to have a statement be nil if a condition isn&#39;t met, but in this case the condition is that x is unwrapped (thus valid for the call). This basically lets you use it like a &quot;retroactive&quot; conditional, it&#39;d be nice to get the same x? behaviour on for loops anyway (letting you unwrap values that way, and maybe test them too).</div></div></blockquote><div><br></div><div>`let value = (x == nil) ? nil : foo.bar(x: x)` isn&#39;t so bad, is it?</div></div></div></div></div></blockquote><div><br></div></div></div><div>In my opinion, it is.</div></div></div></blockquote><div><br></div><div>It certainly isn&#39;t much longer, and its meaning is clear to anyone with a basic grasp of Swift. What makes it bad, in your opinion?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>And you’d even need to write `foo.bar(x: x!)`, right?</div></div></div></blockquote><div><br></div><div>You would. That&#39;s my bad.</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span class=""><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>You could even write a custom operator to sugar it.</div></div></div></div></div></blockquote></span></div></div></blockquote><div> </div><div>```</div><div><div>infix operator ??? : NilCoalescingPrecedence</div><div>func ??? &lt;T&gt;(lhs: [Any?], rhs: @autoclosure () -&gt; T) -&gt; T? {</div><div>    for l in lhs {</div><div>        if l == nil { return nil }</div><div>    }</div><div>    return rhs()</div><div>}</div><div><br></div><div>var x: Int?</div><div>var y: Int?</div><div><br></div><div>(x, y) = (nil, nil)</div><div><br></div><div>[x, y] ??? x! * y!</div><div>// nil<br></div><div><br></div><div>(x, y) = (1, 2)</div><div><br></div><div>[x, y] ??? x! * y!</div><div>// Optional(2)</div></div><div>```</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span class=""><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>______________________________<wbr>_________________<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/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div></div>
</div></blockquote></span></div><br></div></blockquote></div><br></div></div>