[Pitch] Replace the ternary operator with an in-language function


(Charlotte Angela Tortorella) #1

Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.


(Austin Zheng) #2

Strong -1. I don't feel like stylistic concerns alone are a good enough reason to introduce a change that will undoubtedly break source compatibility for many, many projects come Swift 4.

That aside, I don't agree with the arguments that the ternary operator is confusing.

1. If you don't know that it exists, you aren't hampered in writing code. The most straightforward solution, and a perfectly good one, is to use an if-else to assign a value to either a `var` or a `let`.

2. If someone new to Swift thinks `?` and `:` are confusing, I really doubt they will react any better to a generic extension method on a type (which is a primitive in other languages) which takes two "@autoclosure" higher-order function parameters.

Finally, if you don't find any of the arguments above confusing, why force a breaking change by removing ?: instead of just adding the bool extension, especially given the source stability goals of Swift 4 and beyond?

Best,
Austin

···

On Oct 25, 2016, at 9:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org> wrote:

Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

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


(Chéyo Jiménez) #3

Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

You state the issue beautifully. Previous attempts have been "Complete mess" I agree. This is a commonly proposed feature and your solution unfortunately is not new. :frowning:

Replace ?: ternary operator: Definitely magical, but it serves a very important use-case for terse selection of different values. Proposals for alternatives have been intensely discussed, but none have been "better enough" for it to make sense to diverge from the precedent established by the C family of languages.

···

On Oct 25, 2016, at 9:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org> wrote:

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code

This proposal is breaking and would require migration.

Alternatives considered

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

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


(David Goodine) #4

-1 as well, particularly agreeing with Rimantas that removing something of use because it confuses new programmers is not a good motivation. To paraphrase Einstein, ‚ÄúA programming language should be as simple as possible, but no simpler.‚ÄĚ

-d

···

On Oct 26, 2016, at 6:26 AM, Rimantas Liubertas via swift-evolution <swift-evolution@swift.org> wrote:

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

-1

A lot of things can and will be confusing for newcomers, that's not the reason to remove them. Being a newbie is a transitional state.
OTOH, I've never got why ternary is considered especially confusing, for me it never was a problem and I love the terseness of it.
Only total novices in programming may be surprised by it, but they will be suprised by a lot of things anyway, so ternary is the least of their problems. Those with experiene in other languages will be most likely already familiar with the
operator.
Also, many come to Swift from Objective C, which not only has ternary, but also supports a variant where you can use it kind of like ?? in Swift: NSString *other = someString ?: @"default string".

Removing ?: gains nothing and loses a lot, I'd say.

Best regards,
Rimantas
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Mike Kasianowicz) #5

I like the idea in theory, but I also like the existing ternary operator.
Could some of this be accomplished without drastic changes?

Some alternative ideas-

1) Codify ternary operator declaration in the language, but make some
common-sense restrictions to reduce expression parsing complexity (no line
breaks, enforced parens, 'simple' arguments, stuff like that). If there
were an extension like you propose in addition, my preference would be a
verb like "select".

2) Make it a binary operator with autoclosure tuple on the RHS (is it
possible to put autoclosure within a tuple?):

public static func ?<T>(_ value: Bool, _ branches: (_ t: @autoclosure () ->
T, _ f: @autoclosure () -> T)) -> T {
        if value {
            return branches.t()
        } else {
            return branches.f()
        }
    }

···

On Tue, Oct 25, 2016 at 11:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org> wrote:

Preamble: I've read over the threads that already exist about the ternary
operator and to be honest they're a complete mess without a single fully
formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning
curve for newcomers when it comes to dealing with the ternary function. The
best way to do that, in my opinion, is to remove it entirely and add a new
function with better semantics that takes care of ternary operations
entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++,
Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other
languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped
the
ternary operator (e.g. [Go](https://golang.org/doc/
faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/
rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to
increase
the familiarity of the Swift language for C family developers, at the
expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it
requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for
variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and
were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be
proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a
language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that
have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/
If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is
identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me
more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've
provided
four for consideration in this proposal, but are open to other options as
well.
This proposal is much more about the concept than the naming of the
replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f:
@autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () ->
T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () ->
T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T)
-> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

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


(Joshua Alvarado) #6

-1

I love the idea of challenging the syntax but without any real benefit I can see it harder for new devs and it will cause breaking changes that doesn't outweigh the cause. The syntax z ? x : y is not hard to comprehend and expresses powerful statements in just a simple line. I do agree it is abused. It is used in places that a fuller if statement would help make sense of the code. It is on the developer to help make the operator easier to understand. The operator is the same across many languages which helps create a standard.

Alvarado, Joshua

···

On Oct 26, 2016, at 9:12 AM, Mark Sands via swift-evolution <swift-evolution@swift.org> wrote:

Strong +1 from me.

This simply feels like the right approach for Swift, as we see the language head in a direction that has abandoned traditional C-style idioms. As swift has already dropped support for the ++/-- operators and C-style for loops it makes logical sense that dropping the ternary operator (or replacing with a more Swift-like idiom) should follow.

As a side note, after upgrading my swift code to Swift 3, I feel as though I've become un-phased at future source breaking changes until full stability is met and set in stone. If they're worth it, bring them on, I say.

Mark

On Wed, Oct 26, 2016 at 8:52 AM, Mike Kasianowicz via swift-evolution <swift-evolution@swift.org> wrote:
I like the idea in theory, but I also like the existing ternary operator. Could some of this be accomplished without drastic changes?

Some alternative ideas-

1) Codify ternary operator declaration in the language, but make some common-sense restrictions to reduce expression parsing complexity (no line breaks, enforced parens, 'simple' arguments, stuff like that). If there were an extension like you propose in addition, my preference would be a verb like "select".

2) Make it a binary operator with autoclosure tuple on the RHS (is it possible to put autoclosure within a tuple?):

public static func ?<T>(_ value: Bool, _ branches: (_ t: @autoclosure () -> T, _ f: @autoclosure () -> T)) -> T {
        if value {
            return branches.t()
        } else {
            return branches.f()
        }
    }

On Tue, Oct 25, 2016 at 11:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org> wrote:
Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code

This proposal is breaking and would require migration.

Alternatives considered

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

_______________________________________________
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


(Mark Sands) #7

Strong *+1* from me.

This simply feels like the right approach for Swift, as we see the language
head in a direction that has abandoned traditional C-style idioms. As swift
has already dropped support for the ++/-- operators and C-style for loops
it makes logical sense that dropping the ternary operator (or replacing
with a more Swift-like idiom) should follow.

As a side note, after upgrading my swift code to Swift 3, I feel as though
I've become un-phased at future source breaking changes until full
stability is met and set in stone. If they're worth it, bring them on, I
say.

Mark

···

On Wed, Oct 26, 2016 at 8:52 AM, Mike Kasianowicz via swift-evolution < swift-evolution@swift.org> wrote:

I like the idea in theory, but I also like the existing ternary operator.
Could some of this be accomplished without drastic changes?

Some alternative ideas-

1) Codify ternary operator declaration in the language, but make some
common-sense restrictions to reduce expression parsing complexity (no line
breaks, enforced parens, 'simple' arguments, stuff like that). If there
were an extension like you propose in addition, my preference would be a
verb like "select".

2) Make it a binary operator with autoclosure tuple on the RHS (is it
possible to put autoclosure within a tuple?):

public static func ?<T>(_ value: Bool, _ branches: (_ t: @autoclosure ()
-> T, _ f: @autoclosure () -> T)) -> T {
        if value {
            return branches.t()
        } else {
            return branches.f()
        }
    }

On Tue, Oct 25, 2016 at 11:51 PM, Charlotte Angela Tortorella via > swift-evolution <swift-evolution@swift.org> wrote:

Preamble: I've read over the threads that already exist about the ternary
operator and to be honest they're a complete mess without a single fully
formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning
curve for newcomers when it comes to dealing with the ternary function. The
best way to do that, in my opinion, is to remove it entirely and add a new
function with better semantics that takes care of ternary operations
entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a
holdover
from C. This document is an attempt to provide a clear look at the
ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is
continuity
with C, and other common languages in the extended C family (C++,
Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other
languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped
the
ternary operator (e.g. [Go](https://golang.org/doc/fa
q#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust
-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to
increase
the familiarity of the Swift language for C family developers, at the
expense
of newcomers. Established developers do much better with learning
concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it
requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for
variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine
and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be
proposed
for Swift. Higher clarity can be achieved with common language features
by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a
language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier,
have
eschewed the usage of the ternary operator entirely. Other languages
that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/I
f-then-else#Is_If-Then-Else_so_important.3F). `if then else` is
identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me
more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've
provided
four for consideration in this proposal, but are open to other options as
well.
This proposal is much more about the concept than the naming of the
replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f:
@autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure ()
-> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () ->
T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () ->
T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

_______________________________________________
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


(William Sumner) #8

Training users to expect source-breaking churn would be highly damaging to the language. The removal of C-style for loops and increment/decrement operators came with sufficient justification beyond their being inherited from C. I don’t think there’s a sufficient justification for this change, especially with the bar set high for such changes.

Preston

···

On Oct 26, 2016, at 9:12 AM, Mark Sands via swift-evolution <swift-evolution@swift.org> wrote:

Strong +1 from me.

This simply feels like the right approach for Swift, as we see the language head in a direction that has abandoned traditional C-style idioms. As swift has already dropped support for the ++/-- operators and C-style for loops it makes logical sense that dropping the ternary operator (or replacing with a more Swift-like idiom) should follow.

As a side note, after upgrading my swift code to Swift 3, I feel as though I've become un-phased at future source breaking changes until full stability is met and set in stone. If they're worth it, bring them on, I say.


(Erica Sadun) #9

You and I discussed this at length in iOS Folks, but I'll restate here. I'd be against this proposal. I think it adds unnecessary verbosity vs a simple and elegant representation. As an inherently functional alternative to if-then-else, Swift's ternary form is clear and parsimonious, perfect for simple expressions. Converting to a more laborious syntax takes away these advantages, and I'd be tempted to write my own operators to mimic their functionality rather than use your syntax.

I'm glad you brought the proposal here and thank you for your effort in writing it up.

-- E

···

On Oct 25, 2016, at 10:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org> wrote:

Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function


(Mark Sands) #10

Training users to expect source-breaking churn would be highly damaging to

the language. The removal of C-style for loops and increment/decrement
operators came with sufficient justification beyond their being inherited
from C. I don’t think there’s a sufficient justification for this change,
especially with the bar set high for such changes.

Preston

My apologies for skewing the conversation off-topic. I think what I meant
to imply is that we shouldn't be afraid of a deprecation warning. Migrating
away from a ternary operator is trivial, and the consequences usually come
with better readability.

Ignoring my statement about "leftovers from C" opposition, I *do* think
there is sufficient and very strong justification from the 10 items that
Charlotte has listed. I think it would be more valuable if one could pick
apart each bullet point they find excusable and list their reasons why it's
not compelling enough to warrant change.


(Soroush Khanlou) #11

+1 from me as well.

I was initially unconvinced, until Charlotte showed me her proposal. She lays out the case very well, and I agreed to help edit the proposal.

It’s a confusing and bad operator, and it doesn’t give us anything that a function on Bool can’t give us. The way I see it, this isn’t very different from C-style for loops, the ++ operator, or explicit optionality, which are all features where Swift departs from traditional C orthodoxy.

It’s easy to abuse and hard to reason about. Special cases like this operator have to really earn their place in the language. This one doesn’t carry its weight.

Soroush

···

On Oct 26, 2016, at 11:42 AM, Joshua Alvarado via swift-evolution <swift-evolution@swift.org> wrote:

-1

I love the idea of challenging the syntax but without any real benefit I can see it harder for new devs and it will cause breaking changes that doesn't outweigh the cause. The syntax z ? x : y is not hard to comprehend and expresses powerful statements in just a simple line. I do agree it is abused. It is used in places that a fuller if statement would help make sense of the code. It is on the developer to help make the operator easier to understand. The operator is the same across many languages which helps create a standard.

Alvarado, Joshua

On Oct 26, 2016, at 9:12 AM, Mark Sands via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Strong +1 from me.

This simply feels like the right approach for Swift, as we see the language head in a direction that has abandoned traditional C-style idioms. As swift has already dropped support for the ++/-- operators and C-style for loops it makes logical sense that dropping the ternary operator (or replacing with a more Swift-like idiom) should follow.

As a side note, after upgrading my swift code to Swift 3, I feel as though I've become un-phased at future source breaking changes until full stability is met and set in stone. If they're worth it, bring them on, I say.

Mark

On Wed, Oct 26, 2016 at 8:52 AM, Mike Kasianowicz via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I like the idea in theory, but I also like the existing ternary operator. Could some of this be accomplished without drastic changes?

Some alternative ideas-

1) Codify ternary operator declaration in the language, but make some common-sense restrictions to reduce expression parsing complexity (no line breaks, enforced parens, 'simple' arguments, stuff like that). If there were an extension like you propose in addition, my preference would be a verb like "select".

2) Make it a binary operator with autoclosure tuple on the RHS (is it possible to put autoclosure within a tuple?):

public static func ?<T>(_ value: Bool, _ branches: (_ t: @autoclosure () -> T, _ f: @autoclosure () -> T)) -> T {
        if value {
            return branches.t()
        } else {
            return branches.f()
        }
    }

On Tue, Oct 25, 2016 at 11:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

_______________________________________________
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


(Anton Zhilin) #12

infix operator :spades:ÔłŹ : LogicalDisjunctionPrecedenceinfix operator :heart: :
LogicalDisjunctionPrecedence
func :spades:ÔłŹ<T>(lhs: Bool, rhs: @autoclosure () throws -> T) rethrows -> T? {
    if lhs { return rhs() } else { return nil }
}func :heart:<T>(lhs: T?, rhs: @autoclosure () throws -> T) rethrows -> T {
    return lhs ?? rhs
}
// Equivalent statements:
condition() ? first() : second()
condition() :spades:ÔłŹ first() :heart: second()

By removal of ?:, we could simplify our system of operators and prevent
some ternary-related bugs/unexpected stuff. We could modify reserved
operators to allow ? instead of :spades:ÔłŹ and : instead of :heart:.
‚Äč


(Rimantas Liubertas) #13

Pitch: I'd like to simplify the syntax, compiler complexity and learning
curve for newcomers when it comes to dealing with the ternary function. The
best way to do that, in my opinion, is to remove it entirely and add a new
function with better semantics that takes care of ternary operations
entirely within the Swift language.

-1

A lot of things can and will be confusing for newcomers, that's not the
reason to remove them. Being a newbie is a transitional state.
OTOH, I've never got why ternary is considered especially confusing, for me
it never was a problem and I love the terseness of it.
Only total novices in programming may be surprised by it, but they will be
suprised by a lot of things anyway, so ternary is the least of their
problems. Those with experiene in other languages will be most likely
already familiar with the
operator.
Also, many come to Swift from Objective C, which not only has ternary, but
also supports a variant where you can use it kind of like ?? in Swift:
NSString *other = someString ?: @"default string".

Removing ?: gains nothing and loses a lot, I'd say.

Best regards,
Rimantas


(Charlotte Angela Tortorella) #14

Addressing breaking source code: this is something that an auto migrator could extremely easily be written for.

Addressing your first point, `?:` has the advantage of terseness. Your solution requires a lot of code repetition and invariably a programmer will eventually have to deal with `?:` when interacting with literally anyone else's code.

Addressing your second point, `?:` has no function signature. Thus we should be comparing at call-site value. A Bool extension that mentions `true` and `false` in the function signature is far more readable than the magical operator of `?:`.

Addressing your "finally", you've completely missed the argument about removing complexity from the compiler, considering how `?:` requires special handling.

···

On 26 Oct. 2016, at 4:04 pm, Austin Zheng <austinzheng@gmail.com> wrote:

Strong -1. I don't feel like stylistic concerns alone are a good enough reason to introduce a change that will undoubtedly break source compatibility for many, many projects come Swift 4.

That aside, I don't agree with the arguments that the ternary operator is confusing.

1. If you don't know that it exists, you aren't hampered in writing code. The most straightforward solution, and a perfectly good one, is to use an if-else to assign a value to either a `var` or a `let`.

2. If someone new to Swift thinks `?` and `:` are confusing, I really doubt they will react any better to a generic extension method on a type (which is a primitive in other languages) which takes two "@autoclosure" higher-order function parameters.

Finally, if you don't find any of the arguments above confusing, why force a breaking change by removing ?: instead of just adding the bool extension, especially given the source stability goals of Swift 4 and beyond?

Best,
Austin

On Oct 25, 2016, at 9:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

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


(Jon Akhtar) #15

I think that we need to get past the ‚Äúleftovers from C‚ÄĚ being a bad thing mindset. Familiar constructs make Swift easier for programmers (its target audience) easier to learn.

Point by point:

¬†¬†1. Being a holdover from C isn‚Äôt a bad thing. We can take things that were useful in C and make them part of Swift. Who said C language elements were a non-goal of Swift. And to the ‚Äúternary operator is hard to learn‚ÄĚ point. This point gets made over and over in proposals to change Swift, ease of learning is like performance and security ‚Äď you can never have enough so there is no counter-argument. If you can‚Äôt learn the ternary operator, Swift isn‚Äôt the language for you, because what are you going to do when you get to generics and higher order functions.
  2. If the ternary operator adds complexity to the compiler then it really isn’t a holdover from C. We have quite a long time to know how to parse it from our C legacy.
  3. See #1, new users are always confused about everything. They don’t stay that way. The language doesn’t need to be tuned to support it’s non-users. Most developers understand the ternary operator, and it is useful to them. Who is this language for?
¬†¬†4. The ‚Äú:‚ÄĚ appears in other places in the grammar. So what. So do parenthesis and brackets. It is just a token used in a grammar rule as a separator, it doesn‚Äôt have a meaning on its own, and it shouldn‚Äôt have one that isn‚Äôt its function.
  5. So your argument is to make the ternary expression longer to discourage nesting. This is much different than the argument for function(a++, ++a) where order of function parameter evaluation influenced the code, but was not expressed by it. Everything is fully expressed by the ternary operator including order of evaluation.
¬†¬†6. I see no problem with it being limited to bool. I don‚Äôt want Javascript‚Äôs ‚Äú‚ÄĚ == false.
  7. What would be proposed (and has been) is the if expression which is more verbose but easier to read
  8. Again, the C hate.
  9. You leave out the reason for those languages to leave out the ternary operator. What was their rationale?
  10. I’m sorry you had a hard time with it. But you learned it, and now you can apply that knowledge to any language that has it. To add to the anecdotal evidence you provided, I did not have a hard time learning it.

I can distill this down to ‚ÄúC is old and not modern so lets get rid of anything from C‚ÄĚ and ‚ÄúI had a hard time learning the ternary operator"

Bottom line, most developers know the ternary expression if they come from C, C++, Obj-C, Java, C# (The list goes on). Why does Swift need to be different for style reasons. We will be making a niche language, because what you learn isn’t portable to another language like it is if you learn Java, then get a job programming in C#.

···

From: <swift-evolution-bounces@swift.org<mailto:swift-evolution-bounces@swift.org>> on behalf of Mark Sands via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>>
Reply-To: Mark Sands <marksands07@gmail.com<mailto:marksands07@gmail.com>>
Date: Wednesday, October 26, 2016 at 09:55
To: William Sumner <prestonsumner@me.com<mailto:prestonsumner@me.com>>
Cc: Swift-Evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>>
Subject: [External] Re: [swift-evolution] [Pitch] Replace the ternary operator with an in-language function

Training users to expect source-breaking churn would be highly damaging to the language. The removal of C-style for loops and increment/decrement operators came with sufficient justification beyond their being inherited from C. I don’t think there’s a sufficient justification for this change, especially with the bar set high for such changes.

Preston

My apologies for skewing the conversation off-topic. I think what I meant to imply is that we shouldn't be afraid of a deprecation warning. Migrating away from a ternary operator is trivial, and the consequences usually come with better readability.

Ignoring my statement about "leftovers from C" opposition, I do think there is sufficient and very strong justification from the 10 items that Charlotte has listed. I think it would be more valuable if one could pick apart each bullet point they find excusable and list their reasons why it's not compelling enough to warrant change.
+ V2 Checkin API
+ V2 Checkout API
+ V2 Get Admission Records [Updated]
+ V2 Get Scan Records
- New SQLite Data File generation
- V2 Get User Events
- V2 Scan Record Submission

- GDO Ticket Purchase Integration API

- V2 Get Ticket Record(s) [New]
- V2 Ticket Creation API [Updated]
- V2 Ticket Info API [New]
- V2 Ticket Transfer API [New]
- V2 Ticket Re-issue API [New]


(David Sweeris) #16

I'm not sure proposals should do exactly what they claim is a downside of the current approach. Especially when the downside in question is inherent to the problem being solved.

FWIW, the only thing I find confusing about the ternary operator is that I can't overload it. Being able to define my own ternary operators would be great, but I don't have an answer to obvious potential ambiguities.

- Dave Sweeris

···

On Oct 25, 2016, at 23:51, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org> wrote:

Disadvantages of The Ternary Operator

[...]

6. This operator is only applicable to a single type, `Bool`.

[...]

Proposed Approach

We should drop the ternary operator in favor of a new extension to `Bool`.


(Paul Cantrell) #17

I’d like to put in a word in appreciate of such a careful presentation of the idea. While it doesn’t change the fact that this is out of scope for Swift 4, it’s nice to read something so thoughtfully spelled out. Charlotte, I hope you’ll keep bringing your ideas.

FWIW, while I rather like the ternary operator, I’m also a fan of promoting existing if statements to expressions. I hope that we can revisit that discussion in the future.

Cheers,

Paul

···

On Oct 25, 2016, at 11:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org> wrote:

Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

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


(Xiaodi Wu) #18

As Chris mentioned, such a proposal is entirely out of scope for this phase
of Swift 4, it's a commonly rejected proposal that required a high bar for
reconsideration even during the Swift 3 evolution process, and that bar is
even higher going forward because source breaking changes will be extremely
frowned upon. Because it's such a high-traffic list, this is really not an
ideal thread to resurrect...

···

On Fri, Oct 28, 2016 at 5:56 PM Soroush Khanlou via swift-evolution < swift-evolution@swift.org> wrote:

+1 from me as well.

I was initially unconvinced, until Charlotte showed me her proposal. She
lays out the case very well, and I agreed to help edit the proposal.

It’s a confusing and bad operator, and it doesn’t give us anything that a
function on Bool can’t give us. The way I see it, this isn’t very different
from C-style for loops, the ++ operator, or explicit optionality, which are
all features where Swift departs from traditional C orthodoxy.

It’s easy to abuse and hard to reason about. Special cases like this
operator have to really earn their place in the language. This one doesn’t
carry its weight.

Soroush

On Oct 26, 2016, at 11:42 AM, Joshua Alvarado via swift-evolution < > swift-evolution@swift.org> wrote:

-1

I love the idea of challenging the syntax but without any real benefit I
can see it harder for new devs and it will cause breaking changes that
doesn't outweigh the cause. The syntax z ? x : y is not hard to comprehend
and expresses powerful statements in just a simple line. I do agree it is
abused. It is used in places that a fuller if statement would help make
sense of the code. It is on the developer to help make the operator easier
to understand. The operator is the same across many languages which helps
create a standard.

Alvarado, Joshua

On Oct 26, 2016, at 9:12 AM, Mark Sands via swift-evolution < > swift-evolution@swift.org> wrote:

Strong *+1* from me.

This simply feels like the right approach for Swift, as we see the
language head in a direction that has abandoned traditional C-style idioms.
As swift has already dropped support for the ++/-- operators and C-style
for loops it makes logical sense that dropping the ternary operator (or
replacing with a more Swift-like idiom) should follow.

As a side note, after upgrading my swift code to Swift 3, I feel as though
I've become un-phased at future source breaking changes until full
stability is met and set in stone. If they're worth it, bring them on, I
say.

Mark

On Wed, Oct 26, 2016 at 8:52 AM, Mike Kasianowicz via swift-evolution < > swift-evolution@swift.org> wrote:

I like the idea in theory, but I also like the existing ternary operator.
Could some of this be accomplished without drastic changes?

Some alternative ideas-

1) Codify ternary operator declaration in the language, but make some
common-sense restrictions to reduce expression parsing complexity (no line
breaks, enforced parens, 'simple' arguments, stuff like that). If there
were an extension like you propose in addition, my preference would be a
verb like "select".

2) Make it a binary operator with autoclosure tuple on the RHS (is it
possible to put autoclosure within a tuple?):

public static func ?<T>(_ value: Bool, _ branches: (_ t: @autoclosure ()
-> T, _ f: @autoclosure () -> T)) -> T {
        if value {
            return branches.t()
        } else {
            return branches.f()
        }
    }

On Tue, Oct 25, 2016 at 11:51 PM, Charlotte Angela Tortorella via > swift-evolution <swift-evolution@swift.org> wrote:

Preamble: I've read over the threads that already exist about the ternary
operator and to be honest they're a complete mess without a single fully
formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning
curve for newcomers when it comes to dealing with the ternary function. The
best way to do that, in my opinion, is to remove it entirely and add a new
function with better semantics that takes care of ternary operations
entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++,
Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other
languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped
the
ternary operator (e.g. [Go](
https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](
https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to
increase
the familiarity of the Swift language for C family developers, at the
expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it
requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for
variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and
were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be
proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a
language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that
have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](
https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F).
`if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me
more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've
provided
four for consideration in this proposal, but are open to other options as
well.
This proposal is much more about the concept than the naming of the
replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f:
@autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () ->
T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () ->
T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T)
-> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered
<https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

_______________________________________________
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


(Austin Zheng) #19

Addressing breaking source code: this is something that an auto migrator could extremely easily be written for.

Auto migrators are:
- Specific to Xcode, and therefore OS X Swift development using a very specific toolchain
- Less than reliable for large projects
- Not a replacement for the Swift 4 source stability goal.

Addressing your first point, `?:` has the advantage of terseness. Your solution requires a lot of code repetition and invariably a programmer will eventually have to deal with `?:` when interacting with literally anyone else's code.

So, a programmer learns what '?:' means the first time she encounters it and knows what it does for the rest of her life, can recognize it when she sees it in the many other languages which support it, and can take advantage of its terseness if she chooses. I don't see any downsides.

Addressing your second point, `?:` has no function signature. Thus we should be comparing at call-site value. A Bool extension that mentions `true` and `false` in the function signature is far more readable than the magical operator of `?:`.

I don't agree that any of your functions are more readable than "?:", to any significantly greater degree than a `plus()` function would be more readable than `+`, but that's probably just a matter of taste. `??` is another magic operator, one that has far less prior art than `?:`; why not kill that one first?

Addressing your "finally", you've completely missed the argument about removing complexity from the compiler, considering how `?:` requires special handling.

I don't think it's a worthwhile tradeoff. We had a proposal a few months back to remove associated type inference, which would have greatly simplified the type checker and fixed a number of critical bugs. It was rejected due to the impact it would have on developer ergonomics. Compiler complexity is not necessarily a more important goal than user experience.

···

On Oct 25, 2016, at 10:13 PM, Charlotte Angela Tortorella <charlotte.tortorella@icloud.com> wrote:

On 26 Oct. 2016, at 4:04 pm, Austin Zheng <austinzheng@gmail.com <mailto:austinzheng@gmail.com>> wrote:

Strong -1. I don't feel like stylistic concerns alone are a good enough reason to introduce a change that will undoubtedly break source compatibility for many, many projects come Swift 4.

That aside, I don't agree with the arguments that the ternary operator is confusing.

1. If you don't know that it exists, you aren't hampered in writing code. The most straightforward solution, and a perfectly good one, is to use an if-else to assign a value to either a `var` or a `let`.

2. If someone new to Swift thinks `?` and `:` are confusing, I really doubt they will react any better to a generic extension method on a type (which is a primitive in other languages) which takes two "@autoclosure" higher-order function parameters.

Finally, if you don't find any of the arguments above confusing, why force a breaking change by removing ?: instead of just adding the bool extension, especially given the source stability goals of Swift 4 and beyond?

Best,
Austin

On Oct 25, 2016, at 9:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

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


(Charlotte Angela Tortorella) #20

Not a replacement for the Swift 4 source stability goal.

Swift 4 doesn't actually have a source stability goal. It has an ABI stability goal. These are two very different things. ABI is the calling conventions of the language.

So, a programmer learns what '?:' means the first time she encounters it and knows what it does for the rest of her life, can recognize it when she sees it in the many other languages which support it, and can take advantage of its terseness if she chooses. I don't see any downsides.

It's still confusing to learn and conveys no meaning by virtue of its symbols. Sure, everyone learns what something does and then knows how to use it, that doesn't change that certain things are less intuitive and create a higher barrier of entry to the language until one can be considered "fluent".

I don't agree that any of your functions are more readable than "?:"

A function that explicitly states what is being returned for certain states of the `Bool` are implicitly more readable than nothing at all.

to any significantly greater degree than a `plus()` function would be more readable than `+`

`+` is a familiar mathematical concept and conveys its meaning to the layperson quite well. `?:` has no such analogue and conveys nothing to the layperson.

`??` is another magic operator, one that has far less prior art than `?:`; why not kill that one first?

Prior art is no guarantor of quality, case in point `?:`.

···

On 26 Oct. 2016, at 4:20 pm, Austin Zheng <austinzheng@gmail.com> wrote:

On Oct 25, 2016, at 10:13 PM, Charlotte Angela Tortorella <charlotte.tortorella@icloud.com <mailto:charlotte.tortorella@icloud.com>> wrote:

Addressing breaking source code: this is something that an auto migrator could extremely easily be written for.

Auto migrators are:
- Specific to Xcode, and therefore OS X Swift development using a very specific toolchain
- Less than reliable for large projects
- Not a replacement for the Swift 4 source stability goal.

Addressing your first point, `?:` has the advantage of terseness. Your solution requires a lot of code repetition and invariably a programmer will eventually have to deal with `?:` when interacting with literally anyone else's code.

So, a programmer learns what '?:' means the first time she encounters it and knows what it does for the rest of her life, can recognize it when she sees it in the many other languages which support it, and can take advantage of its terseness if she chooses. I don't see any downsides.

Addressing your second point, `?:` has no function signature. Thus we should be comparing at call-site value. A Bool extension that mentions `true` and `false` in the function signature is far more readable than the magical operator of `?:`.

I don't agree that any of your functions are more readable than "?:", to any significantly greater degree than a `plus()` function would be more readable than `+`, but that's probably just a matter of taste. `??` is another magic operator, one that has far less prior art than `?:`; why not kill that one first?

Addressing your "finally", you've completely missed the argument about removing complexity from the compiler, considering how `?:` requires special handling.

I don't think it's a worthwhile tradeoff. We had a proposal a few months back to remove associated type inference, which would have greatly simplified the type checker and fixed a number of critical bugs. It was rejected due to the impact it would have on developer ergonomics. Compiler complexity is not necessarily a more important goal than user experience.

On 26 Oct. 2016, at 4:04 pm, Austin Zheng <austinzheng@gmail.com <mailto:austinzheng@gmail.com>> wrote:

Strong -1. I don't feel like stylistic concerns alone are a good enough reason to introduce a change that will undoubtedly break source compatibility for many, many projects come Swift 4.

That aside, I don't agree with the arguments that the ternary operator is confusing.

1. If you don't know that it exists, you aren't hampered in writing code. The most straightforward solution, and a perfectly good one, is to use an if-else to assign a value to either a `var` or a `let`.

2. If someone new to Swift thinks `?` and `:` are confusing, I really doubt they will react any better to a generic extension method on a type (which is a primitive in other languages) which takes two "@autoclosure" higher-order function parameters.

Finally, if you don't find any of the arguments above confusing, why force a breaking change by removing ?: instead of just adding the bool extension, especially given the source stability goals of Swift 4 and beyond?

Best,
Austin

On Oct 25, 2016, at 9:51 PM, Charlotte Angela Tortorella via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Preamble: I've read over the threads that already exist about the ternary operator and to be honest they're a complete mess without a single fully formed proposal.

Pitch: I'd like to simplify the syntax, compiler complexity and learning curve for newcomers when it comes to dealing with the ternary function. The best way to do that, in my opinion, is to remove it entirely and add a new function with better semantics that takes care of ternary operations entirely within the Swift language.

gist: https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c

Replace the `?:` operator with an in-language function

Proposal: TBD
Author: [Charlotte Tortorella](https://github.com/qata)
Editor: [Soroush Khanlou](https://github.com/khanlou)
Review Manager: TBD
Status: TBD

Introduction <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#introduction>

The ternary operator in Swift was added early in development, as a holdover
from C. This document is an attempt to provide a clear look at the ternary
operator without the baggage of the languages that came before, and comes
to the conclusion that we should deprecate and remove the ternary operator
in favor of an extension to `Bool`.

As a quick refresher, here's what the ternary operator looks like:

let a = 10
let b = 20
// If a is less than b, sets e to "foo", else sets e to "bar"
let e = a < b ? "foo" : "bar"

Advantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#advantages-of-the-ternary-operator>

The primary advantage of this operator is its terseness and expressive
capability. It's shorthand for (e.g.):

let a = 10
let b = 20
let e: String
if a < b {
  e = "foo"
} else {
  e = "bar"
}

The second advantage of Swift supporting the ternary operator is continuity
with C, and other common languages in the extended C family (C++, Objective-C,
Java, C#, Javascript, etc). People coming to Swift from these other languages
may reasonably expect this operator to exist. That said, there are also
popular languages which have kept the majority of C operators but dropped the
ternary operator (e.g. [Go](https://golang.org/doc/faq#Does_Go_have_a_ternary_form) and [Rust](https://github.com/rust-lang/rfcs/issues/1362)).

Disadvantages of The Ternary Operator <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#disadvantages-of-the-ternary-operator>

1. The existence of the ternary operator as a holdover from C is to increase
the familiarity of the Swift language for C family developers, at the expense
of newcomers. Established developers do much better with learning concepts
than newcomers to programming and probably don't need their hands held
with this carry over of an operator.

2. The ternary operator adds complexity to the compiler, because it requires
special handling. It is the only operator that requires two components to
work (both the `?` and the `:`), it uses a character that is excluded from
being used in other operators (`:`), and it isn't defined in the standard
library.

3. The ternary operator's usage of `?` can be confusing
to new users. Every other instance of `?` is associated with
`Optional` values.

4. The ternary operator uses `:`, which is already a heavily overloaded
symbol in Swift. `:` is used in hash tables, type annotations for variables,
class inheritance, and protocol conformance.

5. The ternary operator's short length lends it to being abused in the
nested ternary operator anti-pattern. This is similar to the `++` and
`--` operators, which were removed in Swift 3. While they worked fine and were
readable enough when used alone, using them multiple times in a single
expression like `function(a++, ++a)` made them highly unreadable and
confusing.

6. This operator is only applicable to a single type, `Bool`.

7. If the ternary operator weren't in common usage, it would not be proposed
for Swift. Higher clarity can be achieved with common language features by
creating an extension to `Bool`.

8. The ternary operator was created for and is much more suited to a language
like C, where there were no generics and as such no alternative to an
unintuitive operator.

9. Several other modern languages, like Rust and Go discussed earlier, have
eschewed the usage of the ternary operator entirely. Other languages that have
special constructs similar to `?:`, such as `if then else` in Haskell have
[discussed removing it](https://wiki.haskell.org/If-then-else#Is_If-Then-Else_so_important.3F). `if then else` is identical to the `?:` operator,
excepting that it's prefixed by `if`, while `?:` has no prefix.

Example: `if True then 10 else 20`

10. On a more personal and anecdotal note, the ternary operator gave me more
trouble than any other operator when I was first learning how to program.
I’ve also spoken to several other people who expressed similar sentiments
about this operator’s inscrutability.

Proposed Approach <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#proposed-approach>

We should drop the ternary operator in favor of a new extension to `Bool`.
There are a few possibilities for the naming of this function. We've provided
four for consideration in this proposal, but are open to other options as well.
This proposal is much more about the concept than the naming of the replacement
function.

extension Bool {
    /// If `self == true`, returns `t`, otherwise, returns `f`.
    func transformed<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
        if self {
            return t()
        } else {
            return f()
        }
    }

    func when<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(true t: @autoclosure () -> T, false f: @autoclosure () -> T) -> T {
      ...
    }

    func if<T>(then t: @autoclosure () -> T, else f: @autoclosure () -> T) -> T {
      ...
    }
}

Only one of these should be chosen. We're not proposing adding multiple
functions that achieve the same thing.

Example usage:

let a = 10
let b = 20
_ = (a < b).transformed(true: "foo", false: "bar")
_ = (a < b).when(true: "foo", false: "bar")
_ = (a < b).if(true: "foo", false: "bar")
_ = (a < b).if(then: "foo", else: "bar")

Impact on existing code <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#impact-on-existing-code>

This proposal is breaking and would require migration.

Alternatives considered <https://gist.github.com/Qata/25a11c21200f1cf8f43ed78e9ffd727c#alternatives-considered>

Simplest alternative: we could leave the ternary operator as is and not
introduce any new concepts.

It'd also be possible to add an `if then else` Haskell-esque expression.
This would have the disadvantages of still needing special handling by the
compiler. Since this proposal's intention is partially to remove compiler
complexity, this would be counterproductive and would probably confuse new
users in a similar way to how `?:` does.

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