<div dir="ltr">This was discussed in the old forums... ah, those times :)<div><br></div><div>As before, I don'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't* use nearestX without unwrapping</div><div> }</div><div><br></div><div> guard layer != nil else { continue } </div><div> // *can'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"><<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 dir="ltr"><div>A very common pattern in swift code is to "guard let" or "if let" 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'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'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't a good alternative: </div><div>You might suggest force unwrapping variables when they're inside an if or after a guard that checks for nil. While this does allow for the "layer = nil" 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't notice the force unwrap, and unless you're lucky, you probably didn't paste it into an if that checked layer for nil. So you get a crash. Because of this, it'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>