<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body><div>I agree. The motivation of this proposal is laudable, but I'm not sure it actually gains anything over just defining a property of optional type on the type in question. For example, with your Either enum, you might have:<br></div>
<div> </div>
<div><span class="font" style="font-family: menlo, consolas, "courier new", monospace, sans-serif;"> var left: ErrorType?</span><br></div>
<div><span class="font" style="font-family: menlo, consolas, "courier new", monospace, sans-serif;"> var right: Value?</span><br></div>
<div> </div>
<div>This requires no language changes and allows the use of if-let and optional chaining. It also allows you to expose your different variants as optional, instead of assuming that only one variant is special. <br></div>
<div> </div>
<div>-Kevin Ballard</div>
<div> </div>
<div>On Mon, Dec 7, 2015, at 01:38 PM, Paul Cantrell via swift-evolution wrote:<br></div>
<blockquote type="cite"><div><div><div><div><div style="font-family:Helvetica, Arial;">I like the sentiment of this proposal, but I’m not sure it provides clear value. We already have a generalized version of “if let” in the form of “if case”:<br></div>
<div style="font-family:Helvetica, Arial;"> </div>
<div><div><div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(50, 62, 125)">func</span> foo(either: <span class="colour" style="color:rgb(88, 126, 168)">Either</span><<span class="colour" style="color:rgb(88, 126, 168)">String</span>>) -> <span class="colour" style="color:rgb(88, 126, 168)">String</span> {<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(50, 62, 125)">if</span> <span class="colour" style="color:rgb(50, 62, 125)">case</span> .Right(<span class="colour" style="color:rgb(50, 62, 125)">let</span> string) = either {<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(50, 62, 125)">return</span> string<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"> } <span class="colour" style="color:rgb(50, 62, 125)">else</span> {<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(50, 62, 125)">return</span> <span class="colour" style="color:rgb(132, 62, 100)">"No value"</span><br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"> }<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"> }<br></div>
<div> </div>
<div>This works with cascades just fine:<br></div>
<div> </div>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(50, 62, 125)">if</span> <span class="colour" style="color:rgb(50, 62, 125)">case</span> .Right(<span class="colour" style="color:rgb(50, 62, 125)">let</span> string0) = either0,<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"> .Right(<span class="colour" style="color:rgb(50, 62, 125)">let</span> string1) = either1,<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:10.5px;line-height:normal;font-family:Menlo;"> .Right(<span class="colour" style="color:rgb(50, 62, 125)">let</span> string2) = either2 {<br></div>
<div> </div>
<div>Leaving aside that Swift’s “if case” syntax is a bit clumsy and hard to remember at first, does a <span class="font" style="font-family:Helvetica, ' Arial'">CustomOptionalConvertible really grant additional benefit in terms of either safety or readability?</span><br></div>
<div> </div>
<div><span class="font" style="font-family:Helvetica, ' Arial'">Cheers,</span><br></div>
<div> </div>
<div><span class="font" style="font-family:Helvetica, ' Arial'">Paul</span><br></div>
<div> </div>
<div> </div>
<div><blockquote type="cite"><div>On Dec 7, 2015, at 2:58 PM, <a href="mailto:krzysztof@siejkowski.net">krzysztof@siejkowski.net</a> via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div>
<div> </div>
<div><div style="font-family:Helvetica, Arial;font-size:13px;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;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;">Hi,<br></div>
<div style="font-family:Helvetica, Arial;font-size:13px;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;"> </div>
<div style="font-family:Helvetica, Arial;font-size:13px;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;"> </div>
<div style="font-family:Helvetica, Arial;font-size:13px;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;"># Introduction<br></div>
<div> </div>
<div style="font-family:Helvetica, Arial;font-size:13px;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;"><div>I'd like to propose a non-invasive way of extending the funtionality of `if let` conditional binding (and potencially other Optional-related language constructs) by introducing `CustomOptionalConvertible` protocol. The idea is basically the same as with `CustomStringConvertible` protocol used to provide string interpolation or with `~=` operator used in `switch` statement pattern matching. I believe it's going to simplity and unify the use of the Optional-related family of Swift syntax constructs for custom types.<br></div>
<div> </div>
<div>The proposal is in a draft stage right now, I'll clear it up if it proves worth to be pull-requested.<br></div>
<div> </div>
<div> </div>
<div># Motivation<br></div>
<div> </div>
<div>One of the Swift features that are core to it's safety and readability are Optionals. They're important enough to be given special place in the language syntax. Special operators like `?`, `!` or `??`, special casting keywords like `as?`, special conditional binding `if let`. The Optionals, however, might be also seen as a member of larger family of constructs: call them monads, boxes, value containers, computational context bearers. One example of those would be a very similar type going by the name of Either, Try or Result. It can be seen as an Optional that carries some additional information about the reason why the value is absent. That information is not always of our interest and in those cases conditional binding for Either type makes a lot of sense. However, the `if let` syntax is currently exclusively working only for optionals.<br></div>
<div> </div>
<div> </div>
<div># Proposed solution<br></div>
<div> </div>
<div>While I'd love to see Swift introducing a powerful construct similar to Haskell's `do-notation` or Scala's `for-comprehension`, I believe it'd require a significant invasive change in the language implementation (and, possibly, vision). Therefore the proposed solutions is much more humble. Let's introduce the `CustomOptionalConvertible` protocol with signature:<br></div>
<div> </div>
<div>```<br></div>
<div>protocol CustomOptionalConvertible {<br></div>
<div><span style="white-space:pre;"></span>typealias Wrapped<br></div>
<div><span style="white-space:pre;"></span>public var optional: Optional<Wrapped> { get }<br></div>
<div>}<br></div>
<div>```<br></div>
<div> </div>
<div>Such a protocol will provide a way for an arbitrary type to convert to the Optional. All the types implementing this protocol could then be used in conditional binding syntax without explicit declaration of conversion. I do not propose the introduction of general implicit conversion construct, just a special case. The same as `CustomStringConvertible` is a special case of allowing the value to express itself in the string interpolation.`CustomOptionalConvertible` will allow the author of an arbitratry type to integrate with Swift syntax:<br></div>
<div> </div>
<div>```<br></div>
<div>enum Either<Value> {<br></div>
<div><span style="white-space:pre;"></span>case Left(ErrorType)<br></div>
<div><span style="white-space:pre;"></span>case Right(Value)<br></div>
<div>}<br></div>
<div> </div>
<div>extension Either : CustomOptionalConvertible {<br></div>
<div><span style="white-space:pre;"></span>typealias Wrapped = Value<br></div>
<div><span style="white-space:pre;"></span>public var optional: Optional<Value> {<br></div>
<div><span style="white-space:pre;"></span>get {<br></div>
<div><span style="white-space:pre;"></span>switch (self) {<br></div>
<div><span style="white-space:pre;"></span>case .Left(_): return .None<br></div>
<div><span style="white-space:pre;"></span>case .Right(let value): return .Some(value)<br></div>
<div><span style="white-space:pre;"></span>}<br></div>
<div><span style="white-space:pre;"></span>}<br></div>
<div><span style="white-space:pre;"></span>} <br></div>
<div>}<br></div>
<div> </div>
<div>func foo(either: Either<String>) -> String {<br></div>
<div><span style="white-space:pre;"></span>if let string = either {<br></div>
<div><span style="white-space:pre;"></span>return string<br></div>
<div><span style="white-space:pre;"></span>} else {<br></div>
<div><span style="white-space:pre;"></span>return "No value"<br></div>
<div><span style="white-space:pre;"></span>}<br></div>
<div>}<br></div>
<div>```<br></div>
<div> </div>
<div>There is already a similar mechanism available in the context of pattern matching: `~=` operator.<br></div>
<div> </div>
<div> </div>
<div># Impact on the language<br></div>
<div> </div>
<div>While I cannot say much about the impact on the compiler, I believe the introduction will bring no breaking change to the Swift language itself. All the places that are currently requiring Optionals will still require Optionals. <br></div>
<div> </div>
<div>For the language users it'll make it easier to integrate the constructs used in the program with the native syntax, making them easier to use and read. Current solution, namely:<br></div>
<div>```<br></div>
<div>func foo(either: Either<String>) -> String {<br></div>
<div><span style="white-space:pre;"></span>if let string = either.optional {<br></div>
<div><span style="white-space:pre;"></span>return string<br></div>
<div><span style="white-space:pre;"></span>} else {<br></div>
<div><span style="white-space:pre;"></span>return "No value"<br></div>
<div><span style="white-space:pre;"></span>}<br></div>
<div>}<br></div>
<div>```<br></div>
<div>is introducing unnecessary noise in the otherwise neat syntax. The problem escalates when `if let` cascade is used:<br></div>
<div>```<br></div>
<div>if let string = eitherString.optional<br></div>
<div> int = eitherInt.optional<br></div>
<div> array = eitherArray.optional <br></div>
<div>// ...<br></div>
<div>```<br></div>
<div> </div>
<div> </div>
<div># Alternatives considered<br></div>
<div> </div>
<div>The equivalent of Haskell’s `do-notation`. It’s a powerful construct (some say even too powerful, see<span></span><a href="https://wiki.haskell.org/Do_notation_considered_harmful">https://wiki.haskell.org/Do_notation_considered_harmful</a>). However, I can’t imagine it without significant changes to the language syntax (`if let` should return value) and vision (I believe that Optional are syntactic unicorns by design).<br></div>
<div> </div>
<div> </div>
<div>All the best,<br></div>
<div>Krzysztof<br></div>
</div>
<div><img style="font-family:Helvetica, Arial;font-size:13px;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;height:1px !important;width:1px !important;border-top-width:0px !important;border-right-width:0px !important;border-bottom-width:0px !important;border-left-width:0px !important;margin-top:0px !important;margin-right:0px !important;margin-bottom:0px !important;margin-left:0px !important;padding-top:0px !important;padding-right:0px !important;padding-bottom:0px !important;padding-left:0px !important;" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/4ca939bbd2eb3fc7ce15a2393155237c0bd10bf1ce9b17997adfc854a4fc6b39/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3a73476d223643574649375b61383831663365353b6c497542627a6739586168587645484d4d22364d22324039514c6a755d2232424446535753755a673738455969737a4d4c65676f6369684a79677b63686a7273346a67473346746334336a73393a4d22364f6f4579756a476a4966605d2236425f4566405a71753a457539393c644763425d223245584c4f4d2232443a62314738585c643b4635747d4841517f4a51556d22324775326a475945777c43585d637a67776c484341457a4d44333532523d2236416f4769395d2232474b4578544156725131343d67777f676969314848307a554f65454b467d48763d223244556f4059443576695d2236473737366247495d23344/open"><span class="font" style="font-family:Helvetica, Arial"><span class="size" style="font-size:13px"><span></span>_______________________________________________</span></span><br></div>
<div><span class="font" style="font-family:Helvetica, Arial"><span class="size" style="font-size:13px">swift-evolution mailing list</span></span><br></div>
<div><a style="font-family:Helvetica, Arial;font-size:13px;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;" href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div><a style="font-family:Helvetica, Arial;font-size:13px;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;" href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div>
</div>
</blockquote></div>
<div> </div>
<div> <img style="height:1px !important;width:1px !important;border-top-width:0px !important;border-right-width:0px !important;border-bottom-width:0px !important;border-left-width:0px !important;margin-top:0px !important;margin-bottom:0px !important;margin-right:0px !important;margin-left:0px !important;padding-top:0px !important;padding-bottom:0px !important;padding-right:0px !important;padding-left:0px !important;" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/48bff5cded0797fd68237cd3e55dc592a1d0c43170075db13f83716954307e23/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3148765176786c673171614a7d2236454230345272776e45613d223245387b48535a524d4b4d22364f6c474073743755387d6671634e644a777378336367305245735644347573693149774a427d64666e68336566774b427d4a676f484e4c4135476d2232425071343256717d466176335632367576627d67494e685a6e4b6070713875487036545261485374607f494265753954646272385a49473353644d223647487975563a6458413954684c68436a4669497731436230747d22364274513234477363617f6939517b44537e4a5a61746e44575831357a586a5f69445f4f415d23344d23344/open"><br></div>
<div><u>_______________________________________________</u><br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div>
</blockquote><div> </div>
</body>
</html>