Proposal: Replace ?? by an (optional) argument to ?


(Thorsten Seitz) #1

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty when x is nil which is certainly not what is intended.

In addition it would not be clear which default should be used in case of multiple optional chainings happening, i.e. what should be the result of person?(false).address?.(true).isEmpty

-Thorsten

···

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution swift-evolution@swift.org:

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution swift-evolution@swift.org wrote:

Examples:

  • instead of x ?? false, you would have x?(false)
  • instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.


swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
Not loving this. I’m quite happy with ??-coalescing and don’t see
a compelling reason it needs to be “cleaner”. I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

– E


swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Amir Michail) #2

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty when x is nil which is certainly not what is intended.

What about this then: ??(false, x?.isEmpty)

···

On Jan 29, 2016, at 5:03 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

In addition it would not be clear which default should be used in case of multiple optional chainings happening, i.e. what should be the result of person?(false).address?.(true).isEmpty

-Thorsten

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org>:

Not loving this. I'm quite happy with ??-coalescing and don't see
a compelling reason it needs to be "cleaner". I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

-- E

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

Examples:

* instead of x ?? false, you would have x?(false)
* instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Erica Sadun) #3

I know how frustrating it is to throw ideas out and not hear back. So here's my answer: I don't love this either.
I think you're trying to fix something that is fundamentally not only not broken but pretty solid as it is currently deployed.

-- Erica

···

On Jan 29, 2016, at 6:41 AM, Amir Michail <a.michail@me.com> wrote:

On Jan 29, 2016, at 5:03 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty when x is nil which is certainly not what is intended.

What about this then: ??(false, x?.isEmpty)

In addition it would not be clear which default should be used in case of multiple optional chainings happening, i.e. what should be the result of person?(false).address?.(true).isEmpty

-Thorsten

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Not loving this. I'm quite happy with ??-coalescing and don't see
a compelling reason it needs to be "cleaner". I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

-- E

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Examples:

* instead of x ?? false, you would have x?(false)
* instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Craig Cruden) #4

still much worse.

···

On 2016-01-29, at 20:41:06, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 29, 2016, at 5:03 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty when x is nil which is certainly not what is intended.

What about this then: ??(false, x?.isEmpty)

In addition it would not be clear which default should be used in case of multiple optional chainings happening, i.e. what should be the result of person?(false).address?.(true).isEmpty

-Thorsten

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Not loving this. I'm quite happy with ??-coalescing and don't see
a compelling reason it needs to be "cleaner". I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

-- E

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Examples:

* instead of x ?? false, you would have x?(false)
* instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Amir Michail) #5

still much worse.

What about: Bool(x?.isEmpty) // nil and false => false

···

On Jan 29, 2016, at 8:42 AM, Craig Cruden <ccruden@novafore.com> wrote:

On 2016-01-29, at 20:41:06, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 29, 2016, at 5:03 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty when x is nil which is certainly not what is intended.

What about this then: ??(false, x?.isEmpty)

In addition it would not be clear which default should be used in case of multiple optional chainings happening, i.e. what should be the result of person?(false).address?.(true).isEmpty

-Thorsten

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Not loving this. I'm quite happy with ??-coalescing and don't see
a compelling reason it needs to be "cleaner". I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

-- E

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Examples:

* instead of x ?? false, you would have x?(false)
* instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Nikolai Vazquez) #6

The ?? operator is overloaded to take an optional as the second parameter already. So you can simply chain the ?? over and over with the the last being non optional, which will be the value of all others fail.

With that in mind, a firstNonOptional function wouldn't be hard to implement.

···

Sent from my iPad

On Jan 29, 2016, at 9:25 AM, Ross O'Brien via swift-evolution <swift-evolution@swift.org> wrote:

What about it?

"x ?? false" is simple. If x isn't nil, return x; if x is nil, return false.
"x?.isEmpty ?? false" again is already readable; if x isn't nil, return x.isEmpty; if x is nil, return false.

"Bool(x?.isEmpty)" seems be suggesting that the Bool type has a failable initialiser "init?(_: Bool?)". If x is nil, x.isEmpty would be nil, so the resulting Bool would be nil, not false - this code returns a Bool?, which you already had.

"??(false, x?.isEmpty)" ... uses an operator as an identifier, for a start. At best I'd try to interpret this like reduce - take a collection or variadic list of optionals, return the value of the first non-nil else return the "default". Except I'd still put the default at the end, because I can't think why it would be at the start.

So, if the given problem is taking the nil-coalescing and putting it up front, perhaps there should be a global generic function:

func firstNonOptional<T>(possibles:T?..., failsafe:T) -> T
{
    return possibles.reduce(nil, combine:{ $0 ?? $1 }) ?? failsafe
}

On Fri, Jan 29, 2016 at 1:48 PM, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 29, 2016, at 8:42 AM, Craig Cruden <ccruden@novafore.com> wrote:

still much worse.

What about: Bool(x?.isEmpty) // nil and false => false

On 2016-01-29, at 20:41:06, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 29, 2016, at 5:03 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty when x is nil which is certainly not what is intended.

What about this then: ??(false, x?.isEmpty)

In addition it would not be clear which default should be used in case of multiple optional chainings happening, i.e. what should be the result of person?(false).address?.(true).isEmpty

-Thorsten

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org>:

Not loving this. I'm quite happy with ??-coalescing and don't see
a compelling reason it needs to be "cleaner". I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

-- E

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

Examples:

* instead of x ?? false, you would have x?(false)
* instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Amir Michail) #7

What about it?

"x ?? false" is simple. If x isn't nil, return x; if x is nil, return false.
"x?.isEmpty ?? false" again is already readable; if x isn't nil, return x.isEmpty; if x is nil, return false.

"Bool(x?.isEmpty)" seems be suggesting that the Bool type has a failable initialiser "init?(_: Bool?)". If x is nil, x.isEmpty would be nil, so the resulting Bool would be nil, not false - this code returns a Bool?, which you already had.

How about this:

if? !x?.isEmpty { … } // if? nil { … } = if false { … }
while? !x?.isEmpty { … }
etc.

···

On Jan 29, 2016, at 9:25 AM, Ross O'Brien <narrativium+swift@gmail.com> wrote:

"??(false, x?.isEmpty)" ... uses an operator as an identifier, for a start. At best I'd try to interpret this like reduce - take a collection or variadic list of optionals, return the value of the first non-nil else return the "default". Except I'd still put the default at the end, because I can't think why it would be at the start.

So, if the given problem is taking the nil-coalescing and putting it up front, perhaps there should be a global generic function:

func firstNonOptional<T>(possibles:T?..., failsafe:T) -> T
{
    return possibles.reduce(nil, combine:{ $0 ?? $1 }) ?? failsafe
}

On Fri, Jan 29, 2016 at 1:48 PM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 29, 2016, at 8:42 AM, Craig Cruden <ccruden@novafore.com <mailto:ccruden@novafore.com>> wrote:

still much worse.

What about: Bool(x?.isEmpty) // nil and false => false

On 2016-01-29, at 20:41:06, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 29, 2016, at 5:03 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty when x is nil which is certainly not what is intended.

What about this then: ??(false, x?.isEmpty)

In addition it would not be clear which default should be used in case of multiple optional chainings happening, i.e. what should be the result of person?(false).address?.(true).isEmpty

-Thorsten

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Not loving this. I'm quite happy with ??-coalescing and don't see
a compelling reason it needs to be "cleaner". I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

-- E

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Examples:

* instead of x ?? false, you would have x?(false)
* instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Ross O'Brien) #8

What about it?

"x ?? false" is simple. If x isn't nil, return x; if x is nil, return false.
"x?.isEmpty ?? false" again is already readable; if x isn't nil, return
x.isEmpty; if x is nil, return false.

"Bool(x?.isEmpty)" seems be suggesting that the Bool type has a failable
initialiser "init?(_: Bool?)". If x is nil, x.isEmpty would be nil, so the
resulting Bool would be nil, not false - this code returns a Bool?, which
you already had.

"??(false, x?.isEmpty)" ... uses an operator as an identifier, for a start.
At best I'd try to interpret this like reduce - take a collection or
variadic list of optionals, return the value of the first non-nil else
return the "default". Except I'd still put the default at the end, because
I can't think why it would be at the start.

So, if the given problem is taking the nil-coalescing and putting it up
front, perhaps there should be a global generic function:

func firstNonOptional<T>(possibles:T?..., failsafe:T) -> T
{
    return possibles.reduce(nil, combine:{ $0 ?? $1 }) ?? failsafe
}

···

On Fri, Jan 29, 2016 at 1:48 PM, Amir Michail via swift-evolution < swift-evolution@swift.org> wrote:

On Jan 29, 2016, at 8:42 AM, Craig Cruden <ccruden@novafore.com> wrote:

still much worse.

What about: Bool(x?.isEmpty) // nil and false => false

On 2016-01-29, at 20:41:06, Amir Michail via swift-evolution < > swift-evolution@swift.org> wrote:

On Jan 29, 2016, at 5:03 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty
when x is nil which is certainly not what is intended.

What about this then: ??(false, x?.isEmpty)

In addition it would not be clear which default should be used in case of
multiple optional chainings happening, i.e. what should be the result of
person?(false).address?.(true).isEmpty

-Thorsten

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution < > swift-evolution@swift.org>:

Not loving this. I'm quite happy with ??-coalescing and don't see
a compelling reason it needs to be "cleaner". I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

-- E

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution < > swift-evolution@swift.org> wrote:

Examples:

* instead of x ?? false, you would have x?(false)

* instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.

_______________________________________________

swift-evolution mailing list

swift-evolution@swift.org

https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Thorsten Seitz) #9

Hi Amir,

I confess that I’m not really understanding what you don’t like about the operator ??.

Personally I find it very clear and read it as „or else“. The only worthwhile alternative to ?? would be a method on Optional called `orElse()` like e.g. Java has which expresses the notion quite clearly but with a bit more visual clutter than ??:

(x?.isEmpty).orElse(false) // same as x?.isEmpty ?? false

Besides having less visual clutter I see another advantage to the operator ??: when I want to do something similar on the level of functions of type T -> U? instead of values of type U? I could define an operator ??? which works similar to ??
This would not be possible with a method orElse() because AFAIK it is not possible to add methods to functions.
(This idea relates to the thread about having first class partial functions).

Example:

infix operator ??? {}

func ???<T,U>(lhs: T -> U?, rhs: T -> U?) -> T -> U? {
    func result(x: T) -> U? {
        if let res = lhs(x) {
            return res
        }
        else {
            return rhs(x)
        }
    }
    return result
}

func isEven(x: Int) -> String? {
    switch x {
    case x where x % 2 == 0: return "\(x) is even"
    default: return nil
    }
}

func isOdd(x: Int) -> String? {
    switch x {
    case x where x % 2 == 1: return "\(x) is odd"
    default: return nil
    }
}

let f = isEven ??? isOdd

f(3) // => "3 is odd"

-Thorsten

···

Am 29.01.2016 um 17:58 schrieb Amir Michail via swift-evolution <swift-evolution@swift.org>:

On Jan 29, 2016, at 9:25 AM, Ross O'Brien <narrativium+swift@gmail.com <mailto:narrativium+swift@gmail.com>> wrote:

What about it?

"x ?? false" is simple. If x isn't nil, return x; if x is nil, return false.
"x?.isEmpty ?? false" again is already readable; if x isn't nil, return x.isEmpty; if x is nil, return false.

"Bool(x?.isEmpty)" seems be suggesting that the Bool type has a failable initialiser "init?(_: Bool?)". If x is nil, x.isEmpty would be nil, so the resulting Bool would be nil, not false - this code returns a Bool?, which you already had.

How about this:

if? !x?.isEmpty { … } // if? nil { … } = if false { … }
while? !x?.isEmpty { … }
etc.

"??(false, x?.isEmpty)" ... uses an operator as an identifier, for a start. At best I'd try to interpret this like reduce - take a collection or variadic list of optionals, return the value of the first non-nil else return the "default". Except I'd still put the default at the end, because I can't think why it would be at the start.

So, if the given problem is taking the nil-coalescing and putting it up front, perhaps there should be a global generic function:

func firstNonOptional<T>(possibles:T?..., failsafe:T) -> T
{
    return possibles.reduce(nil, combine:{ $0 ?? $1 }) ?? failsafe
}

On Fri, Jan 29, 2016 at 1:48 PM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 29, 2016, at 8:42 AM, Craig Cruden <ccruden@novafore.com <mailto:ccruden@novafore.com>> wrote:

still much worse.

What about: Bool(x?.isEmpty) // nil and false => false

On 2016-01-29, at 20:41:06, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 29, 2016, at 5:03 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

I agree with Erica. The ?? operator is very readable IMO.

Furthermore x?(false).isEmpty looks like it would evaluate false.isEmpty when x is nil which is certainly not what is intended.

What about this then: ??(false, x?.isEmpty)

In addition it would not be clear which default should be used in case of multiple optional chainings happening, i.e. what should be the result of person?(false).address?.(true).isEmpty

-Thorsten

Am 26. Januar 2016 um 03:29 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Not loving this. I'm quite happy with ??-coalescing and don't see
a compelling reason it needs to be "cleaner". I find your suggested
enhancement less readable. Looks like an optional chaining across
a function.

-- E

On Jan 25, 2016, at 7:03 PM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Examples:

* instead of x ?? false, you would have x?(false)
* instead of x?.isEmpty ?? false, you would have x?(false).isEmpty

I think this change would result in cleaner looking code.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution