[swift-evolution] Allow let binding of non-optionals

Jacob Bandes-Storch jtbandes at gmail.com
Thu Jan 7 02:46:00 CST 2016


+1. I've had a hard time cleaning up certain pieces of code that involve
multiple optional chains and condition checks.

One solution I came up with, but have never used in practice (because it's
too obscure), is this:

    extension Equatable {
        func *except*(excludedValue: Self) -> Self? {
            return self == excludedValue ? nil : self
        }
    }

Then you can make a non-optional Equatable value into an Optional by
checking against a known excluded value:

    if let input = inputs.first, ...,
        let matchLoc = regex.rangeOfFirstMatchInString(...).location.
*except*(NSNotFound)
    {
        // Do something with matchLoc
    } else ...


Another, more flexible, option is to make a new protocol with an extension
that provides similar functionality, but with a closure argument. Then you
unfortunately have to add a trivial conformance for any type you need to
use.

    protocol Satisfying {}
    extension Satisfying {
        func *satisfying*(@noescape predicate: Self -> Bool) -> Self? {
            return predicate(self) ? self : nil
        }
    }

    extension NSRange: Satisfying {}

    if let input = inputs.first, ...,
        let matchRange = regex.rangeOfFirstMatchInString(...).*satisfying*({
$0.location != NSNotFound })
    {
        // Do something with matchRange
    } else ...


To be clear, here's what the user *wants* to do; the clearest code:

    if let input = inputs.first, ...,
        let matchRange = regex.rangeOfFirstMatchInString(...)
        *where* matchRange.location != NSNotFound
    {
        // Do something with matchRange
    } else ...

But that's not allowed, because rangeOfFirstMatchInString returns a
non-optional NSRange.

(Arguably this is a bug to be fixed in the regex API, which should be
replacing NSRange with Range<Int>?, but it's a good example of something
that crops up in plenty of other places.)

Jacob

On Wed, Jan 6, 2016 at 11:06 PM, Krzysztof Siejkowski via swift-evolution <
swift-evolution at swift.org> wrote:

> FWIW, not sure if it fits your desired outcome, but some time ago I’ve
> proposed the idea of `CustomOptionalConvertible` protocol:
>
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/000918.html
>
>
> This could be used to extend the let binding syntax to any arbitrary type,
> as long as the user provides the valid translation to Optional<Type>.
>
> The proposal, unfortunately, did not get a lot of attention at the time.
>
> The main drawback to such a solution for your case is that
> CustomOptionalConvertible is an opt-in mechanism, so you’d need to write
> the implementation of CustomOptionalConvertible to each type you wish to
> let bind:
>
> extension Type : CustomOptionalConvertible {
> typealias Wrapped = Type
> public var optional: Optional<Type> { get {
> return .Some(self)
> }}
> }
>
> Would the necessity for the above boilerplate be a show-stopper to you?
> If so, would you rather see the extension of let bind syntax as default on
> for all the types?
>
> Cheers,
> Krzysztof
>
>
> On 7 January 2016 at 07:41:06, Russ Bishop via swift-evolution (
> swift-evolution at swift.org) wrote:
>
> I often want to bind variables to a specific scope, or perhaps I have
> three optionals I want to bind and one non-optional. (Often I need that
> non-optional value as part of a where condition check but not being able to
> bind it means I leak the variable to the outer scope).
>
> Not being able to bind non-optionals breaks the flow of the code and
> forces me to make a minor context switch when it really doesn’t matter, nor
> does it aid code clarity.
>
>
> Does anyone have strong thoughts about this? I tried searching the
> evolution repo and the mailing list and didn’t see anything.
>
>
> —russ
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160107/451fa4e2/attachment.html>


More information about the swift-evolution mailing list