<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">Am 02.02.2016 um 07:44 schrieb ilya via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt;:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I respectfully disagree with the need for bind operator, see below:<br class=""><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Feb 1, 2016 at 8:18 PM, Erica Sadun via swift-evolution<span class="Apple-converted-space">&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="Apple-converted-space">&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="">Joe says "<span style="font-family: Palatino-Roman;" class="">If you all are serious about this, I think you should start a new thread about it."&nbsp;</span><div class="">I think it's worth a serious discussion just so it can be evaluated and either adopted or discarded</div><div class="">and dropped forever. Here goes.</div><div class=""><br class=""></div><div class="">INTRO</div><div class=""><br class=""><div class="">The<span class="Apple-converted-space">&nbsp;</span><font face="Menlo" class="">if let x = x {...}</font><span class="Apple-converted-space">&nbsp;</span>and<span class="Apple-converted-space">&nbsp;</span><font face="Menlo" class="">guard let x = x else {...}</font><span class="Apple-converted-space">&nbsp;</span>constructs do something with&nbsp;<font face="Menlo" class="">let</font><span class="Apple-converted-space">&nbsp;</span>(and&nbsp;<font face="Menlo" class="">var</font>) that's&nbsp;</div><div class="">fundamentally different from<span class="Apple-converted-space">&nbsp;</span><font face="Menlo" class="">let</font><span class="Apple-converted-space">&nbsp;</span>(and<span class="Apple-converted-space">&nbsp;</span><font face="Menlo" class="">var</font>) elsewhere in the language.&nbsp; The same keywords are used to conditionally unwrap</div><div class="">and bind an item, not just shadow that item's current value.</div></div></div></blockquote><div class=""><br class=""></div><div class=""><span style="font-family: Menlo;" class="">let A = B</span>&nbsp;does exactly the same in all instances: evaluate the expression B in current scope and bind the result to a local name A, and&nbsp;<span style="font-family: Menlo;" class="">if let x = x</span>&nbsp;meaning is no different. If a person doesn't know the precise meaning of if let, with the similarity to normal let one is likely to guess at least the "name binding" part. This is a big advantage of if let syntax.</div></div></div></div></div></blockquote><div><br class=""></div><div>The meaning of `if let x = y` differs from `let x = y` in the type inferred for x (non-optional vs. optional).&nbsp;</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" 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 style="word-wrap: break-word;" class=""><div class=""><div class=""><br class=""></div><div class="">Introducing a new&nbsp;<font face="Menlo" class="">bind</font>&nbsp;keyword to indicate unwrapping and binding would disambiguate these uses.</div><div class=""><br class=""></div><div class="">DETAIL DESIGN:</div><div class=""><br class=""></div><div class="">Jacob Bandes-Storch offers two common use-cases. I prefer his "if bind foo" to my original "if bind foo = foo":</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class="">&nbsp;<span class="Apple-converted-space">&nbsp;</span>if bind foo {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>// foo is non-optional in here</font></div><div class=""><font face="Menlo" class="">&nbsp;<span class="Apple-converted-space">&nbsp;</span>}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Let's consider the case where foo was originally a property. Unfortunately, the syntax above is then very likely to confuse people into thinking that self.foo is non-optional inside the inner scope, which is far from guaranteed:</div></div></div></div></div></blockquote><div><br class=""></div>Actually that semantics (I would prefer `exists` to `bind` to make this more explicit in the syntax) is the whole point of flow typing.</div><div><br class=""></div><div><br class=""></div><div><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><span style="font-family: Menlo;" class="">if bind foo {</span><br class=""></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // we have created a local variable foo here</span></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // foo is non-optional</span></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // no guarantees about self.foo can be made, however</span></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // as it's value may have changed</span></div><div class=""><span style="font-family: Menlo;" class="">}</span></div><div class=""><br class=""></div><div class="">The same applies if foo is a local variable&nbsp;captured by an escaped closure which may be executing concurrently with the inner block.</div></div></div></div></div></blockquote><div><br class=""></div><div><div>In Ceylon flow typing is only allowed for constants (i.e. let bindings), probably for that reason, so foo would have to be constant and the problem you mention would not exist.</div><div><br class=""></div><div>In Ceylon if `foo` is a variable you have to rebind to a constant which looks like follows (Swiftified, and I’m using `exists` rather than `bind` because I don’t like the latter for the aforementioned reason):</div><div><br class=""></div><div><font face="Menlo" class="">// foo is a var</font></div><div><font face="Menlo" class="">if exists x = foo {</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; // x is a let binding to foo</font></div><div><font face="Menlo" class="">}</font></div><div class=""><br class=""></div></div><div>So this is exactly the same as Swift’s current `if let x = foo` except that it makes the unwrapping (or mapping as Erica pointed out) clear and can be used without a (possibly shadowing) assignment for constant values (`if exists x { … }` vs. `if let x = x { … }`).</div><div><br class=""></div><div>As I already posted in the original thread `if var` would have to be expressed more clumsily as `if exists x { var copy = x … }` like originally proposed in SE-0003 (that part was recently thankfully revoked). With `exists` there would be no additional shadowing (`if let x = x { let copy = x … } `) so it might be not so bad.</div><div><br class=""></div><div><br class=""></div><div>There is a potential advantage of the current `if let` syntax, though: it would allow to be generalized to work for monadic types, i.e. it might just be desugared into `map`.&nbsp;</div><div>This could be extended to `for` loops where `for x in foo, y in bar { … }` would be desugared into `flatMap` for all `in` expressions but the last which would be desugared into `map`. In both cases a `where` clause would be desugared into `filter`. For a type to be applicable in `if let` statements it would have to conform to a protocol providing `map`, for support of `where` clauses it would have to conform to another protocol providing `filter` and for being used in `for` statements with nesting it would have to conform to yet another protocol providing `flatMap`.&nbsp;</div><div><br class=""></div><div>In that case I’d definitely prefer to stay with the current syntax, because `let` makes more sense in a generalization than `exists` which only applies to optionals.</div><div><br class=""></div><div>I think that’s the direction I’d prefer most.</div><div><br class=""></div><div>-Thorsten</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class="">So it seems like the bind statement is most helpful only when foo is a local name and either declared with let or not captured by any escaped closure. In that case the original foo can be used directly without shadowing.&nbsp;</div><div class=""><br class=""></div><div class="">One sees how such a statement can be useful, but I'm not sure if the word bind is the best one for it. After all, both let and var perform name binding. Also, there were suggestions to make&nbsp;</div><div class=""><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div><div class=""><span style="font-family: Menlo;" class="">// foo is local and not escaping</span></div><div class=""><span style="font-family: Menlo;" class="">if foo != nil {</span><br class=""></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // foo is non-optional</span><br class=""></div><div class=""><span style="font-family: Menlo;" class="">}</span><br class=""></div></div><div class=""><br class=""></div><div class="">simply work without any additional syntax. Perhaps one can look into that.</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 style="word-wrap: break-word;" class=""><div class=""><div class=""><div class=""><font face="Menlo" class=""></font></div><div class=""><font face="Menlo" class="">&nbsp;<span class="Apple-converted-space">&nbsp;</span>somethingAsync { [weak self] in</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>guard bind self else { return }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span>// ...</font></div><div class=""><font face="Menlo" class="">&nbsp;<span class="Apple-converted-space">&nbsp;</span>}</font></div></div><div class=""><br class=""></div></div><div class="">JBS's approach offers my original "bind" keyword to unwrap and shadow bind, but also provides a way to&nbsp;</div><div class="">strongly bind a weak reference to self, which (presumably) would allow self semantics in the remaining</div><div class="">lifetime of that scope.</div><div class=""><br class=""></div><div class="">ALTERNATIVE PROPOSALS:</div><div class=""><br class=""></div><div class="">Tino Heth proposes a second use-case one with different semantics. This case, it seems to make an</div><div class="">alias rather than using binding for shadowing:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">bind x = a.property.with.a.long.path<br class="">print x &nbsp;// 42<br class="">print(a.property.with.a.long.path == 42) =&gt; true</font></div><div class=""><span style="font-family: Palatino-Roman;" class=""><br class=""></span></div><div class=""><span style="font-family: Palatino-Roman;" class="">presumably this means:</span></div><div class=""><span style="font-family: Palatino-Roman;" class=""><br class=""></span></div><div class=""><font face="Menlo" class="">x += 1</font></div><div class=""><font face="Menlo" class="">print(a.property.with.a.long.path) &nbsp;// 43</font></div><div class=""><font face="Palatino-Roman" class=""><br class=""></font></div><div class=""><font face="Palatino-Roman" class="">DISCUSSION</font></div><div class=""><font face="Palatino-Roman" class=""><br class=""></font></div><div class=""><font face="Palatino-Roman" class="">I'm throwing these both out there. I have nothing to really say about Tino's but I do think my and Jacob's&nbsp;</font></div><div class=""><font face="Palatino-Roman" class="">proposal has the advantages of:</font></div><div class=""><font face="Palatino-Roman" class=""><br class=""></font></div><div class=""><font face="Palatino-Roman" class="">* Simplifying an mildly complex and potentially misleading statement&nbsp;</font></div><div class=""><font face="Palatino-Roman" class="">* Creating a deliberate and controlled rather than accidental shadowing style</font></div><div class=""><font face="Palatino-Roman" class=""><br class=""></font></div><div class=""><font face="Palatino-Roman" class="">Have at it.</font></div><span class=""><font color="#888888" class=""><div class=""><font face="Palatino-Roman" class=""><br class=""></font></div></font></span></div></blockquote><div class=""><br class=""></div><div class="">The 'big picture argument' &nbsp;is that shadowing is likely to introduce more errors, so we should be discouraging it, not encouraging. In real life I find creating a local variable with a different name more natural anyway, e.g:</div><div class=""><br class=""></div><div class=""><div class=""><span style="font-family: Menlo;" class="">//&nbsp;</span><font face="Menlo" class="">issuesViewController is a property</font></div><div class=""><font face="Menlo" class="">// we want to present it, if it can be constructed</font></div><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div><div class=""><span style="font-family: Menlo;" class="">if let to_present = issuesViewController {</span><br class=""></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; presentViewController(to_present, animated: true)</font></div><div class=""><span style="font-family: Menlo;" class="">}</span><br class=""></div></div><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div><div class="">Ilya.</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 style="word-wrap: break-word;" class=""><span class=""><font color="#888888" class=""><div class=""><font face="Palatino-Roman" class=""></font></div><div class=""><font face="Palatino-Roman" class="">-- Erica</font></div><div class=""><font face="Palatino-Roman" class=""><br class=""></font></div><div class=""><font face="Palatino-Roman" class=""><br class=""></font></div></font></span></div><br class="">_______________________________________________<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" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""><br class=""></blockquote></div><br class=""></div></div><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></body></html>