[swift-evolution] ternary operator ?: suggestion

Charles Constant charles at charlesism.com
Mon Jan 4 17:45:33 CST 2016


Our ternary-like switch is now in the "commonly_proposed.md" file, which
doesn't bode very well. It puzzles me that there isn't more enthusiasm. Are
we the only ones who get irritated taking up so much space with a "switch"
when all we need to do is transform between two sets of values?

I think we need to revamp the proposal somehow to make the idea clearer,
because it ought to be pretty compelling.

• Does anyone here have better "side by side" examples of code
before/after?

• Can anyone think of a way to revise the (English) language of the
proposal to make it shorter and sweeter?

Apologies for prescribing instead of doing. My only excuse is that I'm "too
busy"




On Mon, Jan 4, 2016 at 3:03 PM, Matthew Johnson via swift-evolution <
swift-evolution at swift.org> wrote:

>
> On Jan 4, 2016, at 2:37 PM, Paul Ossenbruggen via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Good feedback, I am all for making it feel more like swift. Any ideas
> would be welcome. I will also try to come up with some myself.
>
>
> My suggestion is to leave ternary alone and try to come up with a
> ternary-like switch expression that is workable.  I think that is likely
> the best change possible at this point.
>
>
>
> On Jan 4, 2016, at 12:34 PM, Rod Brown <rodney.brown6 at icloud.com> wrote:
>
> For all the proposals I've seen on this topic, I have to say -1.
>
> While I agree with the notions surrounding this operator, I've yet to see
> a better alternative presented, and none that feel truly Swift.
>
> If someone has a great proposal, though, I look forward to seeing it.
>
> - Rod
>
> On 5 Jan 2016, at 7:28 AM, Howard Lovatt via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> -1 for me. None of it looks or feels like Swift, more like Haskell. I
> would prefer a library solution for now and remove ?: from the language and
> add a which into the standard library and see how that goes and if there is
> need for more.
>
> Sorry,
>
> Howard.
>
> On 5 Jan 2016, at 7:24 AM, Paul Ossenbruggen via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Any feedback on this? I am rethinking the idea of #( because of the #
> prior usage as a preprocessor directive, but like how it stands out and has
> a meaning.  If no feedback, does it make sense to update my proposal with
> these ideas? Or does this feel like the wrong direction.
>
>
> On Dec 30, 2015, at 8:52 AM, Paul Ossenbruggen <possen at gmail.com> wrote:
>
> Some more ideas, this moves away from the notion that we should make it
> look really close to the ternary but keeps all the benefits of the ternary
> and improves upon it. Since I have been suggesting a breaking change, it is
> a good time to rethink it a bit. With this idea a horizontal line
> (double-dash) separates the control value from the choices, the vertical
> line (bar) indicates none of the above.
>
> Rather than use the ?( as I have suggested in the past, I think #( works
> here, where you can think of it as a numerical index. The advantage of this
> is, it stands out better and leaves ? for optionals only. This works well
> with the list form. In the enum case the index is the enum key. I can see
> that this however may be a problem because # is used for preprocessor like
> directives. I am suggesting though just the #( sequence is treated
> differently. Or the ?( is fine with me as well.
>
> I have gone through a lot of options, some others I looked at are !( which
> could be read as "match stick” paren, where the word “match” matches a
> case, I am pretty sure that would not be considered any better than ?(
> because it is used for optionals. Another is “witch hat paren” ^( which can
> be read as “which”.  This might create a parse problem with "power of"
> though, which maybe using ^[ (hat square bracket) could resolve that but
> not sure if that would create other problems. Some other choices would be
> &(  and @( but did not choose them because  they don’t have meaning to me
> but they do have the advantage of standing out like the #(.
>
> let fa = #(truth -- 1 | 0) // boolean case.
> let fb = #(pickOne -- "A", "B", "C", "D", "E", "F", "G" | "Z”) // list
> form, pick index, zero based.
> let fc = #(color -- .Red: 0xFF0000, .Green: 0x00FF00, .Blue: 0x0000FF |
> 0xFFFFFF) // enum form.
> let fd = #(color -- .Red:    0xFF0000,
>               .Green:  0x00FF00,
>       .Blue:   0x0000FF
>              | 0xFFFFFF) // enum multiline, default: can be used here if
> preferred.
> let fe = #(color -- .Red:    0xFF0000,
>               .Green:  0x00FF00,
>       .Blue:   0x0000FF) // if all cases handled, the last bar is optional
>
> This visually kind of represents what is going on. Horizontal-line directs
> eye to one of the normal choices. Vertical-line says none found stop
> looking and do the otherwise choice. Kind of like a train switch.
>
> The strong feedback was that a replacement has to be usable in places
> where a ternary could be used. So it needs to work on a single line (and
> multiline) and needs to be compact. By having a compact, “else" that is
> possible on a single line.
>
> Comparisons to ternary and other approaches:
> • It is very concise like ternary and can fit in places that a ternary
> does.
> • The horizontal line serves to provide a place to align the choices to
> pick from, not as necessary with ternary.
> • The vertical line stops the eye and indicates this is the “else” or
> “default” choice, the colon does that in ternary but the bar stands out
> more.
> • The parens group the expression, in a way that the ternary does not.
> With a ternary it is not until you get to the question mark and the barely
> visible colon that you realize it is a ternary.
> • The #( indicates immediately that the expression has started unlike a
> ternary.
> • #( clearly show beginning and end of the construct so that it is
> immediately identifiable unlike ternary.
> • Makes quick one line conversions easily achievable just as ternary can
> but allowing more than just boolean.
> • The “else” choice is always last and is compactly represented with
> vertical bar like ternary but more visible. This also differs from the
> switch statement form, in that it is much more compact than “default:"
> • The dash does not create a double colon for enum case as was mentioned
> as a problem in previous designs.
> • All data types for the control are handled the same way, like ternary
> but now supports more than boolean, it supports any enumerable tope.
> • The list form looks like a Array sort of, the enum form looks sort of
> like a Dictionary, this should make it seem familiar.
> • The enum form also supports pattern matching. (see below for examples).
> Which ternary does not.
> • The vast majority of switch statements, at least that I typically use,
> could be done with this and be much more compact and concise. However if
> your needs are more complex, then the switch statement is still available.
> • You get the benefits of automatic type inference where switch statements
> used to assign an expression result don’t let you.
> • It removes a lot of duplicated code compared to a switch statement
> assigning an expression result.
> • It makes it clear that the result of the expression can be a “let” where
> less experienced users may think a “var" is required in a switch statement.
> • The name binding and assignment occurs in one step unlike the switch
> statement, when used to assign an expression result.
> • It always returns a result of an expression like ternary does and will
> enforce that the result is a the same type.
> • Like ternary leaves the formatting choice to the developer for multiline
> and single-line but easily handles both.
> • Searchable with web search unlike ternary.
> • Enum uses the same format as the familiar switch syntax which ternary
> does not.
> • #( stands out more than ?( in my earlier designs.
>
> The difference between this and the switch statement is that this deals
> only in single expressions for each case. There can only be one expression
> that gets selected by the control input. This simplifies things compared to
> a switch statement there are not multiple statements to list afterwards and
> it does not need the word “case" before each part of the choice to separate
> each list of statements. This makes it so that it can be much more compact
> and means the word “case” is not necessary.
>
> Below I go through a bunch of comparisons to statement form, vs new
> expression also different formatting options:
>
> let res : Int
> switch color {
>     case .Red: res = 0xFF0000
>     case .Green: res = 0x00FF00
>     case .Blue: res = 0x0000FF
> default:
>     res = 0xFFFFFF
> }
>
> With the new expression:
>
> let res = #(color -- .Red:   0xFF0000
>           .Green: 0x00FF00
>                      .Blue:  0x0000FF
>                      | 0xFFFFFF}
>
> This uses a where clause with existing statement:
>
> let res : Int
> switch color {
>     case .Red where shade == .Dark: res = 0xFF1010
>     case .Red: res = 0xFF0000
>     case .Green: res = 0x00FF00
>     case .Blue: res = 0x0000FF
>     default:
>         res = 0xFFFFFF
> }
>
> This one way to do the same thing with multiline and the expression if it
> makes it clearer, some may prefer this:
>
> let res = #(color --
>     case .Red where shade == .Dark: 0xFF1010
>     case .Red: 0xFF0000
>     case .Green: 0x00FF00
>     case .Blue: 0x0000FF
>     default: 0xFFFFFF
> }
>
> Since this the case does not add anything, you can do this as well:
>
> let res = #(color —-  .Red where shade == .Dark: 0xFF1010
>
>      .Red:   0xFF0000
>
>      .Green: 0x00FF00
>
>      .Blue:  0x0000FF
>
>      | 0xFFFFFF}
>
>
> If “case” makes the “where" clearer then I am fine requiring it but I
> don’t think it is necessary: To make this kind of formatting easy, the
> editor should help align  with the dashes. To allow more space on each line
> this would also work:
>
> let res = #(color
>     -—   .Red where shade == .Dark: 0xFF1010
>          .Red:   0xFF0000
>          .Green: 0x00FF00
>          .Blue:  0x0000FF
>          | 0xFFFFFF}
>
> one last option for maximum space on the line:
>
> let res = #(color —-
>  .Red where shade == .Dark: 0xFF1010
>  .Red:   0xFF0000
>  .Green: 0x00FF00
>  .Blue:  0x0000FF
>  | 0xFFFFFF}
>
> On Dec 23, 2015, at 11:51 AM, Paul Ossenbruggen <possen at gmail.com> wrote:
>
> Been thinking about the boolean case a bit more, and how to make it better
> than a ternary using my proposed syntax. So else could be put there to help
> show it is the opposite. The downside is this makes it mix keywords and
> operators so seems a bit jarring.
>
> With the new form parenthesis are built into it and are required:
>
> x = ?(x == y : 49 else 3)
>
> alternatively the bang means do the opposite:
>
> x = ?(x == y : 49 ! 3) // not sure this creates a parsing problem.
>
> or if the above causes a parsing problem:
>
> x = ?(x == y : 49 | 3)
>
> Any thoughts?
>
> On Dec 23, 2015, at 7:02 AM, Félix Cloutier via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I know, but that won't support pattern matching.
>
> Félix
>
> Le 23 déc. 2015 à 02:22:07, David Waite <david at alkaline-solutions.com> a
> écrit :
>
> In the case where your input is hashable, you could just do:
>
> let i = [.Red:0xff0000, .Green:0x00ff00, .Blue:0x0000ff][color]
>
> this would mean that color must be a Color and not an Optional<Color>
> (because of swift 2.x limitations)
>
> -DW
>
> On Dec 22, 2015, at 8:04 AM, Félix Cloutier via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I like the gist of it too, though you seem to introduce both a new keyword
> and a new syntax. (To be clear, I like the syntax but I'm ambivalent
> towards reusing switch instead of which.)
>
> My minor suggestions would to avoid braces for things that aren't scopes;
> that either the comma or the the question mark is redundant in their
> current position (you need a start delimiter or an end delimiter but you
> don't need both); and that it needs a way to handle a default case if
> enumeration isn't exhaustive (I'd do that by returning an optional).
>
> let i = which color (.Red: 0xff0000, .Green: 0x00ff00, .Blue: 0x0000ff) ??
> 0x000000
>
>
>
> Thinking out loud, once you remove the question marks it really looks like
> a dictionary literal, so maybe it could even use square brackets to close
> the gap.
>
> let i = which color [.Red: 0xff0000, .Green: 0x00ff00, .Blue: 0x0000ff] ??
> 0x000000
>
>
>
> I thought about subscripting a dictionary literal in place:
>
> [Color.Red: 0xff0000, ...][color] ?? 0x000000
>
>
>
> but that won't support elaborate pattern matching, and I think that this
> is a deal breaker for the functional folks.
>
> Félix
>
> Le 22 déc. 2015 à 09:31:32, Charles Constant <charles at charlesism.com> a
> écrit :
>
> Just goofing on this a little. What if we called it a "which" statement,
> instead of a "switch" statement? It's a bit cutesy, but not too verbose,
> and it makes sense if you read it aloud.
>
> let i = which color {
> ? .Red: 0xFF0000,
> ? .Green: 0x00FF00,
> ? .Blue: 0x00000FF
> }
>
> let i = which boo {
> ? true: 1,
> ? false: 0,
> ? nil: -1
> }
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
>  _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
>
>  _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>  _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160104/00afd6e4/attachment.html>


More information about the swift-evolution mailing list