<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><div style="direction: inherit;">Hi,</div><div style="direction: inherit;"><br></div><div style="direction: inherit;">I'd just like to voice my opinion similar to Xiaodi's that the short-circuit is going to create very confusing code. This is the kind of sugar I can see be forbidden by linters that want to reduce surprises.</div></div><div style="direction: inherit;"><br></div><div style="direction: inherit;">David.</div><div><div><div style="direction: inherit;"><br></div><br>Sent from my iPhone</div>On 16 Aug 2016, at 23:47, Maximilian Hünenberger via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div></div><div style="direction: inherit;">Hi Justin,</div><div style="direction: inherit;"><br></div><div style="direction: inherit;">First of all I like your idea!</div><div style="direction: inherit;">Second, I understand the concerns of Xiaodi but I don't think the short-circuit problem is that big. Functions which have a non Void return type mostly have no side effects (at least in my code base).</div><div style="direction: inherit;"><br></div><div style="direction: inherit;">Furthermore the less explicit control flow (only one "?") can be addressed with a keyword in front of the whole expression (e.g. "guard?", "try?") just like my implemented "?" below (which exactly behaves like option 1 and is probably the easiest implementation):</div><div style="direction: inherit;"><br></div><div style="direction: inherit;"><br></div><div style="direction: inherit;">// hacked with throwing mechanism&nbsp;<span style="background-color: rgba(255, 255, 255, 0);">(tested in iPad Playgrounds)</span></div><div style="direction: inherit;"><br></div><div style="direction: inherit;"><div style="direction: inherit;">struct UnwrapError: Error {}</div><div style="direction: inherit;">postfix operator |? {}</div><div style="direction: inherit;">postfix func |? &lt;T&gt;(value: T?) throws -&gt; T {</div><div style="direction: inherit;">&nbsp; &nbsp; guard let value = value else {</div><div style="direction: inherit;">&nbsp; &nbsp; &nbsp; &nbsp; throw UnwrapError()</div><div style="direction: inherit;">&nbsp; &nbsp; }</div><div style="direction: inherit;">&nbsp; &nbsp; return value</div><div style="direction: inherit;">}</div></div><div style="direction: inherit;"><br></div><div style="direction: inherit;"><br></div><div style="direction: inherit;">// sample code</div><div style="direction: inherit;"><br></div><div style="direction: inherit;"><div style="direction: inherit;">func f&lt;T&gt;(_ x: T) -&gt; T {</div><div style="direction: inherit;">&nbsp; &nbsp; print("f\(x)")</div><div style="direction: inherit;">&nbsp; &nbsp; return x</div><div style="direction: inherit;">}</div><div style="direction: inherit;">func foo(arg1: Int, arg2: Int, arg3: Int, arg4: Int, arg5: Int) -&gt; Int {</div><div style="direction: inherit;">&nbsp; &nbsp; return arg1 + arg2 + arg3 + arg4 + arg5</div><div style="direction: inherit;">}</div><div style="direction: inherit;"><br></div><div style="direction: inherit;">// prints:</div><div style="direction: inherit;">//f1</div><div style="direction: inherit;">//f2</div><div style="direction: inherit;">// short circuiting from left to right</div><div style="direction: inherit;">let num = try? foo(arg1: f(1), arg2: f(2), arg3: f(Int?.none)|?, arg4: f(4), arg5: f(5))</div><div style="direction: inherit;">num // nil</div><div style="direction: inherit;"><br></div><div style="direction: inherit;">let x = Double("3.141")</div><div style="direction: inherit;">let y = Double("1.41")</div><div style="direction: inherit;">// also works with other operators</div><div style="direction: inherit;">let z = try? x|? + y|?</div><div style="direction: inherit;"><br></div><div style="direction: inherit;"><br></div><div style="direction: inherit;">Best regards&nbsp;</div><div style="direction: inherit;">Maximilian</div><div style="direction: inherit;"><br></div></div><div>Am 16.08.2016 um 19:24 schrieb Justin Jia via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt;:<br><br></div><blockquote type="cite"><div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div></div><div>Thank you for the sharing how you solve this problem! It seems like the best workaround so far.&nbsp;</div><div><br></div><div>I wish $0 can be replaced by the actual name. (Maybe tuples?)</div><div><br></div><div>let a = (x: x, y: y)</div><div>let result = a.my_map { foo(x: $0.x, y: $0.y }</div><div><br></div><div>In my_map unwrap all variables inside tuple?</div><div><br></div><div>I agree that short-circuiting is an issue. But personally I still think the imperfect solution is good enough. But I'll try to find other possible solutions.&nbsp;</div><div><br></div><div>Sincerely,</div><div>Justin</div><div><br>On Aug 16, 2016, at 11:47 PM, Félix Cloutier &lt;<a href="mailto:felixcca@yahoo.ca">felixcca@yahoo.ca</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8">I use map/flatMap when I have an optional parameter to a method:<div class=""><br class=""></div><div class="">let result = x.map { foo.bar(x: $0) }</div><div class=""><br class=""></div><div class="">My only grief is that it doesn't work too well when you have many optionals that you want to unwrap and use as parameters.</div><div class=""><br class=""></div><div class="">I tend to agree that short-circuiting call expressions from their arguments could be confusing, especially for functions that take a lot of parameters (5+, which is not that uncommon in Cocoa), and even more so when you have many short-circuiting parameters. I can see that it wouldn't be too obvious why a function isn't called. With || and &amp;&amp;, the reason that the next condition is called or not is extremely clear.</div><div class=""><br class=""></div><div class="">You could argue that a short-circuiting &amp;&amp; wouldn't make consensus (even though I think it would), but replacing a short-circuiting || results in much uglier code than the code that you're trying to get around with this new short-circuiting argument construct.</div><div class=""><div class="">
<br class="Apple-interchange-newline"><span style="color: rgb(0, 0, 0); font-family: 'Lucida Grande'; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; display: inline !important; float: none;" class="">Félix</span>
</div>
<br class=""><div><blockquote type="cite" class=""><div class="">Le 16 août 2016 à 08:31:50, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; a écrit :</div><br class="Apple-interchange-newline"><div class="">We don't design the language in a vacuum. If statements can short-circuit and function calls can't. You are proposing a function call that can short-circuit. This severely violates user expectations.<br class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Aug 16, 2016 at 10:03 Justin Jia &lt;<a href="mailto:justin.jia.developer@gmail.com" class="">justin.jia.developer@gmail.com</a>&gt; wrote:<br class=""></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" class=""><div class="">I will reply both of your email in this simple email.</div><div class=""><br class=""></div><br class=""><div class=""></div></div><div style="word-wrap:break-word" class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 16, 2016, at 10:26 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><div style="white-space:pre-wrap" class="">Top-replying because Google is forcing me to:<br class=""><br class="">If you want to print an error for all early exits, declare a variable to keep track of exit status such as `var isEarlyExit = false`, then use a defer block that prints `error` only after checking `isEarlyExit` (or, you know, design your code so that `error` itself would be nil if you're exiting without an error).<br class=""><br class=""></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">IMHO `var is EarlyExist = false` is really ugly. Sometimes we can’t design our code so that `error` itself would be nil if existing without an error simply because we de depending on Cocoa Touch and many third party frameworks.&nbsp;</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="white-space:pre-wrap" class="">It is not "really bad" if your code "fails" unless the lines of code are executed in the explicitly written order. There are no tricks hidden in that behavior: lines of code are *supposed* to be executed from top to bottom in the absence of a control flow statement, because Swift is a procedural programming language. Proceeding from one line to the next is the absolute most primitive flow of control.<br class=""><br class=""></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Not always, but sometimes. Maybe I should say it’s “better” if changing the order of the code won’t produce any unintentional behaviors? We are talking about how to improve Swift, right?</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="white-space:pre-wrap" class="">`guard` and `defer` were introduced in a later version of Swift to solve a practical problem encountered in daily use, the nested pyramid of doom from too many `if let` blocks. The point is that `guard` and `defer` together constitute an ingenious and *complete* solution to that problem; you have not shown me any scenario that cannot be trivially refactored to avoid nested blocks using these two language constructs. So more sugar is not necessary to solve this problem.<br class=""><br class=""></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Well, it’s Turing Complete. I can’t argue against it. But I can give you an example that needs multiple defer. I think this greatly hinders readability. Also, I think making our code less order independent is already important enough.</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="white-space:pre-wrap" class="">"This is not explicit enough" *is* an argument against almost any sugar you can propose. I think you are seeing why the core team is actively discouraging sugar proposals on this list. Unless something comes along that totally blows the alternative out of the water, I'm inclined to agree that more sugar is almost a non-goal for Swift.<br class=""><br class="">(What would be something that could change my mind? Here would be my criteria:<br class=""><br class="">* The non-sugared version is extremely painful to write (&gt;&gt;5 LOC, maybe &gt;&gt;20), difficult to write correctly, and even if correctly written, does not express the intended solution clearly to the reader.<br class=""><br class=""></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">I don’t know how many time you spent on writing swift code in the past. I also don’t know whether your code depends on Cocoa or not. At least, personally, this is the no.1 request in my wish list. I think `if let` is extremely painful to write (not because &gt;&gt;20, but because it occurs too often and keeps bugging me). Maybe you feel differently. Then it’s really hard for me to convince you and it’s also really hard for you to convince me. Time will tell how many developers want this feature.</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="white-space:pre-wrap" class="">* There is a single, overwhelmingly obvious, universally or nearly universally appropriate solution, and the proposed sugar would always be a shorthand for that one solution.<br class=""><br class=""></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">If we choose to reinvent if statements, short-circuiting will not be a nearly universally appreciate solution. Not even close.&nbsp;</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="white-space:pre-wrap" class="">Something like a copy-on-write attribute would fit the bill, because good luck implementing that by hand over and over again, and if you're a reader of code, good luck verifying that all that code does what you think.)<br class=""></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Maybe. But’s that’s another story.</div><div class=""><br class=""></div><div class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class="">I have already explained why your proposal is not at all like optional chaining. Your proposal hides complicated control flow changes, but optional chaining does not.<br class=""><br class="">It does not do you any good to argue that "most people won't nest functions inside functions". First of all, that's an unbelievable claim. Second of all, computed properties can have side effects, since they are essentially functions under the hood. Have you never referred to `foo.bar` inside a function call? You literally cannot know if a property is computed, potentially with side effects, unless you inspect the source code. Thus, a programmer cannot know if they "choose to nest functions inside functions". It does not matter if they are a genius.</blockquote></div><div class=""><br class=""></div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class="">Same apply to if statement. IMO, this paragraph can be used to argue against all statements that will short-circuit in some way. I’m still not convinced why `if` can be used but the proposed solution can’t.</div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="gmail_quote"><div dir="ltr" class="">On Mon, Aug 15, 2016 at 23:56 Justin Jia &lt;<a href="mailto:justin.jia.developer@gmail.com" target="_blank" class="">justin.jia.developer@gmail.com</a>&gt; wrote:<br class=""></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" class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 16, 2016, at 1:51 AM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote">On Mon, Aug 15, 2016 at 12:31 PM, Justin Jia <span dir="ltr" class="">&lt;<a href="mailto:justin.jia.developer@gmail.com" target="_blank" class="">justin.jia.developer@gmail.com</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><br class=""></div><div class="">Since you mentioned do and defer:</div><div class=""><br class=""></div><div class="">```</div><div class=""><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="color:#ba2da2" class="">func</span><span class=""> foo(wantsToBreak: </span><span style="color:#703daa" class="">Bool</span><span class="">) {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span class="">&nbsp; &nbsp; out: </span><span style="color:#ba2da2" class="">do</span><span class=""> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color:#ba2da2" class="">defer</span><span class=""> { </span><span style="color:#3e1e81" class="">print</span><span class="">(</span><span style="color:#d12f1b" class="">"Hello, world!"</span><span class="">) }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color:#ba2da2" class="">guard</span><span class=""> wantsToBreak </span><span style="color:#ba2da2" class="">else</span><span class=""> { </span><span style="color:#ba2da2" class="">break</span><span class=""> out }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span class="">&nbsp; &nbsp; }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(209,47,27)" class=""><span class="">&nbsp; &nbsp; </span><span style="color:#3e1e81" class="">print</span><span class="">(</span><span class="">"End of function."</span><span class="">)</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span class="">}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px" class=""><span class=""></span><br class=""></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class=""><span style="color:#31595d" class="">foo</span><span class="">(wantsToBreak: </span><span style="color:#ba2da2" class="">true</span><span class="">) </span><span class="">// Output: Hello, world!\nEnd of function.</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)" class=""><span style="color:#31595d" class="">foo</span><span class="">(wantsToBreak: </span><span style="color:#ba2da2" class="">false</span><span class="">) </span><span class="">// Output: Hello, world!\nEnd of function.</span></div></div><div class=""><span class="">```</span></div><div class=""><span class=""><br class=""></span></div><div class="">Do you think this is confusing?</div></div></blockquote><div class=""><br class=""></div><div class="">No, I don't. But I also don't see why you would put `defer` inside `do` like that. `defer` and `guard` can be used profitably without nesting inside blocks.</div><div class="">&nbsp;</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Because I don’t want `defer` to execute outside do block. Let me give you a simplified example: I wanted to print error for all early exits except normal return (reaches last line). I would like to use defer otherwise I need to write `else { print(error); return }` for all guards. The intuitive way of achieving this for me was to nest defer inside do blocks. But it turned out that defer will be executed even if you choose to break a block. I’m not arguing this is a bad design decision. My point is: sometimes non-intuitive design decisions are non-avoidable.</div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class="">At least it confused me in the fast. However, defer is still very useful.</div><div class=""><br class=""></div><div class="">Even if I choose to use guard, defer and do, it will still look like the one with `if let`. Lots of blocks. The code should be straightforward without any brackets.</div></div></blockquote><div class=""><br class=""></div><div class="">Huh? I don't buy this argument at all. You don't like the look of `{ }`, so you are proposing new sugar using `?`--is that what you're claiming? This sounds to me like the same motivation as that behind early suggestions to move to a Python-like syntax.</div><div class="">&nbsp;</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" class=""><div class="">See this example (since it’s a lot of code I rendered a PDF).</div></div></blockquote><div class=""><br class=""></div><div class="">I don't see the motivation in this example. Why wouldn't you just move the code to update `cell.heading` right after you guard that `imageName` is not nil?</div><div class="">&nbsp;</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">I already explained why. It was just a naive example. In real life methods can be a lot more complicated than my example. It’s really bad if your code will fail unless it follows the same exact order. We need to modify our code everyday, and most of the time we are working on code that is not even written by ourselves. If you scan through methods with name like updateCell, intuitively, you will think the order of the code will not matter. And it shouldn’t! It is really easy to make mistakes with guard statement because the order matters here. IMO, guard is only useful if we place it at the beginning of the function—for all or nothing.</div><div class=""><br class=""></div><div class="">Why we chose to use brackets and indentation? Because they can warn us that the behavior of the code will change. Either the outcome will vary (if) or the code will be executed for more than one time (for). Checking an object if is nil doesn’t always belong here. Using `if let` is not being explicit. It’s boilerplate. A not-so-good fix for the side effect of optionals. Most of the time, we want the flow to be “flat”. That’s why swift supports `guard` and `object?.method`. If you think `foo(x?)` is not important, do you think `guard` and `object?.method` are also not important?</div><div class=""><br class=""></div><div class="">I understand that Swift is designed to be explicit. I also agree with it. But I saw an unhappy trend in the mailing list: "this is not explicit enough" can be used to argue against anything. Shall we remove @autoclosure? Shall we remove trailing closures? Shall we remove `object?.method`?</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 16, 2016, at 1:16 AM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote">On Mon, Aug 15, 2016 at 12:07 PM, Xiaodi Wu<span class="">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt;</span><span class="">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><span class="">On Mon, Aug 15, 2016 at 11:43 AM, Justin Jia<span class="">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:justin.jia.developer@gmail.com" target="_blank" class="">justin.jia.developer@gmail.com</a>&gt;</span><span class="">&nbsp;</span>wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class="">I believe the core team has considered 99% of the ideas in the mailing list in the past, but it doesn’t mean we can’t discuss it, right?</div></div></div></blockquote><div class=""><br class=""></div></span><div class="">No, it certainly doesn't! I'm saying that you haven't come up with a solution to a known problem with the idea.</div><div class=""><div class=""><div class="">&nbsp;</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><div class="">Assuming we have the following declaration:</div><div class=""><br class=""></div><div class="">```</div><div class="">func foo(a: Int, b: Int?, c: Int, d: Int?) -&gt; Int</div><div class="">```</div><div class=""><br class=""></div><div class="">For this:</div><div class=""><br class=""></div><div class="">```</div><div class="">let z = foo(a: f1(), b: f2()?, c: f3(), d: f4()?) // z becomes optional</div><div class="">```</div><div class=""><br class=""></div><div class="">We have a few different “possible solutions”:</div><div class=""><br class=""></div><div class="">1. Short-circuiting from left to right. This is equivalent to:</div><div class=""><br class=""></div><div class="">```</div><div class="">var z: Int? = nil</div><div class="">let a = f1()</div><div class="">guard let b = f2() else { return }</div><div class="">let c = f3()</div><div class="">guard let d = f4() else { return }</div><div class="">z = foo(a: a, b: b, c: c, d: d)</div><div class="">```</div><div class=""><br class=""></div><div class="">2. Short-circuiting from left to right for optionals. Then evaluate non-optional parameters. This is equivalent to:</div><div class=""><br class=""></div><div class="">```</div><div class="">var z: Int? = nil</div><div class="">guard let b = f2() else { return }</div><div class="">guard let d = f4() else { return }</div><div class="">let a = f1()</div><div class="">let c = f3()</div><div class="">z = foo(a: a, b: b, c: c, d: d)</div><div class="">```</div><div class=""><br class=""></div><div class="">3. Do not short-circuiting.</div><div class=""><br class=""></div><div class="">```</div><div class="">var z: Int? = nil</div><div class="">let a = f1()</div><div class="">let optionalB = f2()</div><div class="">let c = f3()</div><div class="">let optionalD = f4()</div><div class="">guard let b = optionalB else { return }</div><div class="">guard let d = optionalD else { return }</div><div class="">z = foo(a: a, b: b, c: c, d: d)</div><div class="">```</div><div class=""><br class=""></div><div class="">Like I said before, I agree that there is no intuitive solution to this problem. However, I'm still not convinced that this feature is *not important*.</div><div class=""><br class=""></div><div class="">Thank you for pointing out the problem to me. I didn't notice it at the time I wrote my first email. I really appreciate that. However, instead of saying I don't know which is the best solution so let's assume the core team made the right decision, we should discuss whether 1, 2, 3 is the best solution. Or you can convince me we don't *need* this feature.</div></div></div></blockquote><div class=""><br class=""></div></div></div><div class="">I'm going to convince you that 1, 2, and 3 are all bad solutions. Thus, this feature won't fly.</div><div class="">The fundamental issue is that having this sugar means that I can no longer reason about the order in which code is executed. An innocuous statement such as `print(a(), b(), c(), d())`, once you mix in your proposed `?` syntax with some but not all of these function calls, might have d() executed before a(), after a(), or not at all. This is greatly damaging to the goal of writing clear, understandable code.</div><span class=""><div class="">&nbsp;</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><div class="">Back to the original topic.</div><div class=""><br class=""></div><div class="">I spent some time thinking and changed my mind again. I think solution 1 is most reasonable. It is consistent with if statements. Instead of treating it as sugar for `if let`, we can treat it as sugar for `guard`, which is much easy to understand and remember.</div><div class=""><br class=""></div><div class="">-</div><div class=""><br class=""></div><div class="">Below is the reason why I think this feature is important (quoted from another email).</div><div class=""><br class=""></div><div class="">The problem with `if let` is you need to call the function inside { }.</div><div class=""><br class=""></div><div class="">```</div><div class="">/* code 1 */</div><span class=""><div class="">if let x = x, let y = y {</div></span><div class="">&nbsp; &nbsp;<span class="">&nbsp;</span>/* code 2, depends on x and y to be non-optional */</div><div class="">&nbsp; &nbsp;<span class="">&nbsp;</span>let z = foo(x, y)</div><div class="">&nbsp; &nbsp;<span class="">&nbsp;</span>if let z = z {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;<span class="">&nbsp;</span>bar(z)</div><div class="">&nbsp; &nbsp;<span class="">&nbsp;</span>}</div><div class="">&nbsp; &nbsp;<span class="">&nbsp;</span>/* code 3, depends on x and y to be non-optional */</div><div class="">}</div><div class="">/* code 4 */</div><div class="">```</div><div class=""><br class=""></div><div class="">I can't use `guard` for this situation because guard will force me to leave the entire function.</div></div></div></blockquote></span></div></div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><span class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><div class="">```</div><div class="">/* code 1 */</div><span class=""><div class="">guard let x = x, y = y else { return }</div></span><div class="">/* code 2, depends on x and y to be non-optional */</div><span class=""><div class="">guard let z = foo(x, y) else { return }</div><div class="">bar(z)</div></span><div class="">/* code 3, depends on x and y to be non-optional */ &lt;- This won't execute if z is nil</div><div class="">/* code 4 */ &lt;- This won't execute if x, y or z is nil</div><span class=""><div class="">```</div></span></div></div></blockquote><div class=""><br class=""></div></span><div class="">Then surround it with a do block.</div><div class=""><br class=""></div><div class="">```</div><div class="">out: do {</div><div class="">&nbsp;<span class="">&nbsp;</span>guard foo else { break out }</div><div class="">&nbsp;<span class="">&nbsp;</span>guard bar else { break out }</div><div class="">&nbsp;<span class="">&nbsp;</span>/* other code */</div><div class=""><div class=""><div class="">}</div><div class="">```</div></div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Or, more idiomatically, since your use case is that you want /* code 4 */ to be executed no matter what, while everything else depends on x and y not being nil:</div><div class=""><br class=""></div><div class="">```</div><div class="">defer { /* code 4 */ }</div><div class="">guard let x = x, let y = y else { return }</div><div class="">/* code 2 */</div><div class="">/* code 3 */</div><div class="">```</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><span class=""><div class=""><br class=""></div><div class="">What I really want is some like this:</div><div class=""><br class=""></div><div class="">```</div><div class="">/ * code 1 */</div></span><span class=""><div class="">let z = foo(x?, y?)</div></span><div class="">/* code 2, depends on x and y to be non-optional, use x? and y? */</div><div class="">bar(z?)</div><div class="">/* code 3, depends on x and y to be non-optional, use x? and y? */</div><div class="">/* code 4 */</div><div class="">```</div><div class="">This is much easier to read. Sometimes people choose to use `guard` to avoid `{ }`, which usually lead to code could easily get wrong (like the second example).</div><div class=""><br class=""></div><div class="">Sincerely,</div><div class="">Justin</div></div><div class=""><div class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 15, 2016, at 11:41 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><div style="white-space:pre-wrap" class="">What do you mean, limited to variables? What about a computed property? You will have the same problem.<br class=""><br class="">I'm not sure where you want to go with this, given that the core team has considered the same idea in the past and found these issues to have no good solution.<br class=""></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Mon, Aug 15, 2016 at 04:56 Justin Jia &lt;<a href="mailto:justin.jia.developer@gmail.com" target="_blank" class="">justin.jia.developer@gmail.com</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="auto" class=""><div class=""></div><div style="direction:inherit" class="">IMO I don't this bar should be evaluated unless we decide if let can accept non-optional values.&nbsp;</div><div style="direction:inherit" class=""><br class=""></div><div style="direction:inherit" class="">Actually, what if we allow if let to accept non-optional values?</div><div style="direction:inherit" class=""><br class=""></div><div style="direction:inherit" class=""><span style="background-color:rgba(255,255,255,0)" class="">I agree this is confusing at the beginning. But people who are not familiar with the detail design can avoid this situation easily. People who are familiar with the design can adopt it quickly. Sometimes, this is unavoidable.&nbsp;</span></div><div style="direction:inherit" class=""><br class=""></div><div style="direction:inherit" class="">Btw, do you think this is still something nice to have if we limit this syntax to only variables?</div></div><div dir="auto" class=""><div class=""><div style="direction:inherit" class=""><br class=""></div>On Aug 15, 2016, at 4:59 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">On Mon, Aug 15, 2016 at 3:55 AM, Xiaodi Wu<span class="">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt;</span><span class="">&nbsp;</span>wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr" class=""><div class=""><div class="">On Mon, Aug 15, 2016 at 3:25 AM, Justin Jia via swift-evolution<span class="">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</span><span class="">&nbsp;</span>wrote:<br class=""></div></div><div class="gmail_extra"><div class="gmail_quote"><div class=""><div class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 15, 2016, at 4:09 PM, Charlie Monroe &lt;<a href="mailto:charlie@charliemonroe.net" target="_blank" class="">charlie@charliemonroe.net</a>&gt; wrote:</div><br class=""><div class=""><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">The example above was to better demonstrate the problem with *when* to evaluate the latter argument. Why should both arguments be evaluated *before* the if statement? If both calls return Optionals,&nbsp;</div><span class=""><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">if let x = bar(42), y = baz(42) { ... }</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div></span><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">is how would I write it without the suggested syntax - baz(42) will *not* be evaluated if bar(42) returns nil. Which bears a question why would&nbsp;</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">foo(bar(42)?, baz(42)?)&nbsp;</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">evaluate both arguments even if the first one is nil, making it incosistent with the rest of the language?</div></div></blockquote></div><br class=""><div class="">I see your point. I understand that maybe 1/2 of the people think we should evaluate both arguments and 1/2 of the people think we should only evaluate the first argument.</div><div class=""><br class=""></div><div class="">I changed my idea a little bit. Now I think you are right. We should only evaluate the first argument in your example. It’s not only because of inconsistent, but also because the language should at least provide a way to “short-circuit” to rest of the arguments.</div><span class=""><div class=""><br class=""></div><div class="">If they want to opt-out this behavior, they can always write:</div><div class=""><br class=""></div><div class="">```</div><div class="">let x = bar(42)</div><div class="">let y = baz(42)</div></span><div class="">foo(x?, y?)</div><div class="">```</div></div></blockquote><div class=""><br class=""></div></div></div><div class="">Well, that was just the easy part. Now, suppose bar is the function that isn't optional.</div><div class=""><br class=""></div><div class="">```</div><div class="">foo(bar(42), baz(42)?)</div><div class="">```</div><div class=""><br class=""></div><div class="">Is bar evaluated if baz returns nil? If you want this syntax to be sugar for if let, then the answer is yes.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">s/yes/no/</div><div class="">&nbsp;</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">If short-circuiting works left-to-right, then the answer is no.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">s/no/yes/&nbsp;</div><div class=""><br class=""></div><div class="">(See? Confusing.)</div><div class="">&nbsp;<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">This is very confusing, and there is no good intuitive answer.&nbsp;<br class=""></div><span class=""><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""></div></div><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote></span></div></div></div></blockquote></div></div></div></div></blockquote></div></blockquote></div></div></blockquote></div></div></div></div></blockquote></div></div></div></div></blockquote></div></div></div></div></blockquote></div><br class=""></div><br class=""></blockquote></div><br class=""></div></div>
</div></blockquote></div></div></blockquote></div>
</div></blockquote></div></div></blockquote></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div></blockquote></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></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>