<div dir="ltr">This was discussed in the old forums... ah, those times :)<div><br></div><div>As before, I don&#39;t think this idea is workable, because this only works for names that describe local variables and only if they are not captured by long-running closures.</div><div><br></div><div>Imagine the code</div><div><br></div><div>class C {</div><div>  var layer: CALayer? { can be changed from other threads }<br></div><div><br></div><div>  func f() {</div><div>    var nearestX = X()</div><div><br></div><div>    doSomethingAsync { </div><div>        nearestX = compute(...) </div><div>    }</div><div><br></div><div>    // later</div><div><div><br></div><div>    if nearestX != nil { </div><div>      // *can&#39;t* use nearestX without unwrapping</div><div>    }</div><div><br></div><div>    guard layer != nil else { continue } </div><div>    // *can&#39;t* use layer without force unwrapping</div></div><div>  }</div><div>}</div><div><br></div><div>This will, however, work if we do create a new name that shadows an old name with if let nearestX = nearestX or guard let layer = layer.</div><div>let here plays an important role by reminding that original nearestX or layer may have already changed in the meantime.</div><div><br></div><div>I agree this shadowing may not look best if nearestX and layer *are* plain old local variables. In that case those names are under your control and I would find this refactoring benefitial:</div><div><br></div><div>    let maybe_nearestX = ... </div><div>    let maybe_layer = ... </div><div><br></div><div><div>    if let nearestX = maybe_nearestX { </div><div>      // use nearestX </div><div>    }</div><div><br></div><div>    guard let layer = maybe_layer else { continue } </div><div>    // use layer </div></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 11, 2015 at 7:11 PM, Daniel Hooper 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>A very common pattern in swift code is to &quot;guard let&quot; or &quot;if let&quot; optionals  - this works by creating a new non-optional variable to be used by future code. Often, the new variable is given the same name as the original optional variable, creating a shadow variable. This approach leads to odd looking code like this:</div><div><br></div><div>if let nearestX = nearestX { closest = nearestX }<br></div><div>guard let layer = layer else { continue } </div><div>// use layer</div><div><br></div><div>At a glance, and to Swift newcomers, this code looks completely non-sensical. It&#39;s also verbose for simply ensuring the variable is non-nil. </div><div><br></div><div>The solution:</div><div>Swift should generate unwrapped shadow variables after nil checking. The compiler would treat the below code as if it had created an unwrapped shadow variable.</div><div><br></div><div><span><div>if nearestX != nil { closest = nearestX } // notice that nearestX isn&#39;t force unwrapped<br></div><div>guard layer != nil else { continue } </div><div>// use layer, without force unwrapping</div></span></div><div><br></div><div>Why force unwrapping isn&#39;t a good alternative: </div><div>You might suggest force unwrapping variables when they&#39;re inside an if or after a guard that checks for nil. While this does allow for the &quot;layer = nil&quot; syntax, it results in code that is less resilient to change. Imagine that this code was written:</div><div><br></div><div>{code:java}</div><div>if layer != nil {</div><div>// lots of code before //</div><div>layer!.backgroundColor = newColor</div><div>// lots of code after //</div><div>}</div><div>{code}</div><div><br></div><div>And much later, you need to use some of the the code in the if body elsewhere, so you copy and paste a huge chunk of it. You likely won&#39;t notice the force unwrap, and unless you&#39;re lucky, you probably didn&#39;t paste it into an if that checked layer for nil. So you get a crash. Because of this, it&#39;s important we make safe optional unwrapping as easy and sensical as possible, and minimize the situations that you would need to force unwrap.</div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=1p9Jer2O6jVE9KWvo-2B9iUaEyN8slp4IizyiLwsfp54Pr96Ag7DxawVu1-2BPVw63yuqjv-2BBclpNsknSPV-2FcfjQPVYWsQEo3xZTae1VthYqsIaEGzzPO-2Fd-2FGB52d8hNaNAU3w8JcwcVb0WfXSn-2FJACq6Xo6jSMBluARHZ60Q9LID5iI0T9E7jYL75n6k01jrs2c2VWuh2e7nMxy3KFOyC4b-2BT5nYU6O-2FhmFmQSVXwsofJw-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
<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>