ternary operator ?: suggestion

I agree - but this isn’t the case i covered.
This is the trivial case of an expression

condition ? value1 : value2

which shouldn’t be done using blocks (my example was really an elaboration function)

i know the ternary operator is nice in this case, but isn’t the following just as easy to write and understand ?
it’s certainly easier to add comments - i know it’s a little longer, but … it’s a style thing i guess

func uriEncode(string: String, encodeSlash: Bool) -> String {
  var encodedString = ""
  for char in string.characters {
    if (char >= "A" && char <= "z") || (char >= "a" && char <= "z") || (char >= "0" && char <= "9") || char == "_" || char == "-" || char == "~" || char == "." {
      encodedString += "\(char)"
    }
    else if char == "/" {
      if encodeSlash {
        encodedString += "%2F” // URL Encoding for Forward Slash
      } else {
        encodedString += "\(char)"
      }
    }
    else {
      let literal = String(char)
      for byte in literal.utf8 {
        encodedString += String(format: "%%2X", arguments: [Int(byte)])
      }
    }
  }
  return encodedString
}

however, if you replace the ternary operator with *anything* we’re asking for someone to come along with and change existing multilayered ?: into the new form.

Such as

return (heapAlign < valueAlign
     ? (valueAlign < elementAlign ? elementAlign : valueAlign)
     : (heapAlign < elementAlign ? elementAlign : heapAlign))

to

return if heapAlign < valueAlign
    (if valueAlign < elementAlign (elementAlign) else (valueAlign))
  else
    (if heapAlign < elementAlign (elementAlign) else (heapAlign))

or

return
  if heapAlign < valueAlign (
    if valueAlign < elementAlign (
      elementAlign
    ) else (
      valueAlign
    )
  ) else (
    if heapAlign < elementAlign (
      elementAlign
    ) else (
      heapAlign
    )
  )

which really doesn’t help - it’s actually easier read as:

return {
  if heapAlign < valueAlign (
    if valueAlign >= elementAlign (
      return valueAlign
    )
  ) else (
    if heapAlign >= elementAlign (
      return heapAlign
    )
  )
  return elementAlign
}()

Use inline blocks for complex logic and the existing else if for trivial cases - even on one or two lines

let width : Int
if highDef {width = 1920} else {width = 720}

if encodeSlash {encodedString += "%2F”}
else {encodedString += "\(char)"}

ABR.

···

On 12 Dec 2015, at 01:31, Drew Crawford via swift-evolution <swift-evolution@swift.org> wrote:

Strong -1, for all the reasons Andrey gave, although I think his point could benefit from examples.

Consider this case from my codebase, for which ?: is natural:

   ///Signature Calculations for the Authorization Header: Transferring Payload in a Single Chunk (AWS Signature Version 4) - Amazon Simple Storage Service
  func uriEncode(string: String, encodeSlash: Bool) -> String {
       var encodedString = ""
       for char in string.characters {
           if (char >= "A" && char <= "z") || (char >= "a" && char <= "z") || (char >= "0" && char <= "9") || char == "_" || char == "-" || char == "~" || char == "." {
               encodedString += "\(char)"
           }
           else if char == "/" {
               encodedString += encodeSlash ? "%2F" : "\(char)"
           }
           else {
               let literal = String(char)
               for byte in literal.utf8 {
                   encodedString += String(format: "%%2X", arguments: [Int(byte)])
               }
           }
       }
       return encodedString
   }

I think replacing with `let foo` and scopes lengthens, emphasizes, and draws attention to a very minor detail, de-emphaizing and obscuring the main idea of the function.

On Dec 11, 2015, at 7:18 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org> wrote:

Strong -1; this turns a quick one-liner into a multiline monstrosity. When massaging coordinates and layouts in iOS apps, ?: is often helpful to handle corner cases inline.

A.

_______________________________________________
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

I meant if else statements. If we introduce the then keyword we could have
and if then expression that is separate from the if else statement.

···

On Fri, Dec 11, 2015 at 5:44 PM, J. Cheyo Jimenez <cheyo@masters3d.com> wrote:

+1 I personally really like the if then expression. I think is cleaner and
this way we can have if else expressions with curly braces too. Introducing
the then keyword also could allow for switch expressions.

let result = switch (yourColor) {
               case .Red then 1
               case .Green then 2
               case .Blue then 3
          }

On Fri, Dec 11, 2015 at 5:31 PM, Al Skipp via swift-evolution < > swift-evolution@swift.org> wrote:

How about:

let v = if condition then “A" else “B"

No mysterious symbols or braces, or multiline monstrosity.

> On 12 Dec 2015, at 01:18, Andrey Tarantsov via swift-evolution < >> swift-evolution@swift.org> wrote:
>
> Strong -1; this turns a quick one-liner into a multiline monstrosity.
When massaging coordinates and layouts in iOS apps, ?: is often helpful to
handle corner cases inline.
>
> A.
>
> _______________________________________________
> 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

I don’t really want to wade into this discussion, but if A and B are intended to be *expressions* instead of an arbitrary sequence of statements|decls|exprs, then a more consistent syntax would be:

  let v = if condition (A) else (b)

The immediate problem with that is that juxtaposition of two expressions (condition, and A [with or without parens]) will lead to immediate syntactic ambiguity.

-Chris

···

On Dec 11, 2015, at 5:36 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org> wrote:

How about:

let v = if condition then “A" else “B"

I don't think introducing a separate "then" keyword is a good idea, two subtly different kinds of IFs would be confusing.

I guess you meant:

let v = if condition { "A" } else { "B” }

So adding “then”:

let v = if condition then “A” else “B”

fixes that ambiguity and “then” would help differentiate an expression from a statement. I think there is value to having them separate constructs (for details see earlier comments in this thread). Also it is nice not having the braces in the expression.

Perhaps, similarly, “then" indicates an expression as opposed to a statement:

let v = switch condition then case Red: 1, case Blue: 2, case Green: 3

One downside is it, It may add confusion as to when to add the “then” clause as people will have to know what an expression vs statement is, but I suppose that is true with a ternary operator as well, and this reads better than a ternary operator. This also provides a good way to do single line switch expressions.

for multiline:

let v = if condition
  then “A”
  else “B"

let v = switch condition then
  case .Red: 1,
  case .Blue: 2,
  case .Green: 3

or with multiple expressions:

let v = switch condition then
  case .Red: 1,
  case .Blue: (if shade == .Dark then 4 else 2),
  case .Green: 3

···

On Dec 11, 2015, at 8:57 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 11, 2015, at 5:36 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

How about:

let v = if condition then “A" else “B"

I don't think introducing a separate "then" keyword is a good idea, two subtly different kinds of IFs would be confusing.

I guess you meant:

let v = if condition { "A" } else { "B” }

I don’t really want to wade into this discussion, but if A and B are intended to be *expressions* instead of an arbitrary sequence of statements|decls|exprs, then a more consistent syntax would be:

  let v = if condition (A) else (b)

The immediate problem with that is that juxtaposition of two expressions (condition, and A [with or without parens]) will lead to immediate syntactic ambiguity.

-Chris

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

I actually agree; I like 'then' in CoffeeScript which is used for the same purpose there.

But:

1) this is a bigger change than just a ternary operator

2) if we add "then", I believe that both forms should be acceptable for both kinds of IF statements

A.

1. I would really hate to explain to someone when if needs a then and when it doesn't. That's the sort of inconsistency that shouldn't be added lightly.

2. As for

  if cond (then-expr) (else-expr)

— this is definitely unreadable, and will cause problems. Even right now, if syntax vs expression syntax is ambiguous:

  if let foo = foos.filter { $0.isBar } {
    ...
  }

3. If we can somehow solve all of this, I think I'll be +1 for replacing (A ? B : C) with some sort of (if A then B else C).

4. Generally, I wonder how hard would it be for all statements to be usable as expressions? Why didn't Swift go that way from the start?

A.

2) "then" would serve a way to differentiate the If statement and an if
expression.

1) I think that making an if-then expression would be less problematic than
making all if else statements into expressions. It was really easy for rust
to just drop ?: because they already had *if* as an expression but in swift
the *if* is a statement.
In swift we have if let and if case; adding if then to handle ternary
operations is probably no so bad.

···

On Fri, Dec 11, 2015 at 5:58 PM, Andrey Tarantsov via swift-evolution < swift-evolution@swift.org> wrote:

I actually agree; I like 'then' in CoffeeScript which is used for the same
purpose there.

But:

1) this is a bigger change than just a ternary operator

2) if we add "then", I believe that both forms should be acceptable for
both kinds of IF statements

A.

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

If at all possible, it’d be good to avoid adding new keywords, however if the keyword ‘then’ could enable 'if expressions’ and ‘switch expressions’, I’d be fully in favour.

Binding to a variable using a switch statement isn’t as elegant as it could be. The ability to define a ‘let’ variable and assigning a value later in a switch statement does help somewhat, but the examples below are very clear and elegant in my opinion. (I’d even question the necessity of the repetitive keyword ‘case’, but maybe that’s a step too far?)

Al

···

On 12 Dec 2015, at 07:15, Paul Ossenbruggen via swift-evolution <swift-evolution@swift.org> wrote:

So adding “then”:

let v = if condition then “A” else “B”

fixes that ambiguity and “then” would help differentiate an expression from a statement. I think there is value to having them separate constructs (for details see earlier comments in this thread). Also it is nice not having the braces in the expression.

Perhaps, similarly, “then" indicates an expression as opposed to a statement:

let v = switch condition then case Red: 1, case Blue: 2, case Green: 3

One downside is it, It may add confusion as to when to add the “then” clause as people will have to know what an expression vs statement is, but I suppose that is true with a ternary operator as well, and this reads better than a ternary operator. This also provides a good way to do single line switch expressions.

for multiline:

let v = if condition
  then “A”
  else “B"

let v = switch condition then
  case .Red: 1,
  case .Blue: 2,
  case .Green: 3

or with multiple expressions:

let v = switch condition then
  case .Red: 1,
  case .Blue: (if shade == .Dark then 4 else 2),
  case .Green: 3

On Dec 11, 2015, at 8:57 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 11, 2015, at 5:36 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

How about:

let v = if condition then “A" else “B"

I don't think introducing a separate "then" keyword is a good idea, two subtly different kinds of IFs would be confusing.

I guess you meant:

let v = if condition { "A" } else { "B” }

I don’t really want to wade into this discussion, but if A and B are intended to be *expressions* instead of an arbitrary sequence of statements|decls|exprs, then a more consistent syntax would be:

  let v = if condition (A) else (b)

The immediate problem with that is that juxtaposition of two expressions (condition, and A [with or without parens]) will lead to immediate syntactic ambiguity.

-Chris

_______________________________________________
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

1. I would really hate to explain to someone when if needs a then and when it doesn't. That's the sort of inconsistency that shouldn't be added lightly.

agreed definitely want to be careful with that. I think with braces meaning statements that differentiation can be made clear. I would certainly start with statements when describing, just as you usually don’t talk about the ternary operator until later.

3. If we can somehow solve all of this, I think I'll be +1 for replacing (A ? B : C) with some sort of (if A then B else C).

Yes that would be great.

4. Generally, I wonder how hard would it be for all statements to be usable as expressions? Why didn't Swift go that way from the start?

The biggest problem statement is you don’t need to exhaustively specify every outcome:

if cond {
  print(“hello”)
}

whereas in an expression you have to specify what happens in the else.

let say = if cond then “hello” else “goodbye"

unless you go seriously off the deep end:

let say = if cond then “hello”

“say" then becomes an optional, *shudder*

···

On Dec 12, 2015, at 12:37 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org> wrote:

I like these expressions with "then" and without braces.

What about using "then" for statements as well?

If condition then {
        ...
} else {
        ...
}

···

Am 12.12.2015 um 08:15 schrieb Paul Ossenbruggen via swift-evolution <swift-evolution@swift.org>:

So adding “then”:

let v = if condition then “A” else “B”

fixes that ambiguity and “then” would help differentiate an expression from a statement. I think there is value to having them separate constructs (for details see earlier comments in this thread). Also it is nice not having the braces in the expression.

Perhaps, similarly, “then" indicates an expression as opposed to a statement:

let v = switch condition then case Red: 1, case Blue: 2, case Green: 3

One downside is it, It may add confusion as to when to add the “then” clause as people will have to know what an expression vs statement is, but I suppose that is true with a ternary operator as well, and this reads better than a ternary operator. This also provides a good way to do single line switch expressions.

for multiline:

let v = if condition
  then “A”
  else “B"

let v = switch condition then
  case .Red: 1,
  case .Blue: 2,
  case .Green: 3

or with multiple expressions:

let v = switch condition then
  case .Red: 1,
  case .Blue: (if shade == .Dark then 4 else 2),
  case .Green: 3

On Dec 11, 2015, at 8:57 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 11, 2015, at 5:36 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org> wrote:

How about:

let v = if condition then “A" else “B"

I don't think introducing a separate "then" keyword is a good idea, two subtly different kinds of IFs would be confusing.

I guess you meant:

let v = if condition { "A" } else { "B” }

I don’t really want to wade into this discussion, but if A and B are intended to be *expressions* instead of an arbitrary sequence of statements|decls|exprs, then a more consistent syntax would be:

  let v = if condition (A) else (b)

The immediate problem with that is that juxtaposition of two expressions (condition, and A [with or without parens]) will lead to immediate syntactic ambiguity.

-Chris

_______________________________________________
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

Implied in using the “then", if…then…else would aways require “else" when using “then” similar to how “guard" requires “else”. This will help to make the difference between statements and expressions clear.

let x = If cond then X else Y

is the full form, where “else" can not be omitted.

···

On Dec 12, 2015, at 12:59 PM, Paul Ossenbruggen <possen@gmail.com> wrote:

On Dec 12, 2015, at 12:37 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. I would really hate to explain to someone when if needs a then and when it doesn't. That's the sort of inconsistency that shouldn't be added lightly.

agreed definitely want to be careful with that. I think with braces meaning statements that differentiation can be made clear. I would certainly start with statements when describing, just as you usually don’t talk about the ternary operator until later.

3. If we can somehow solve all of this, I think I'll be +1 for replacing (A ? B : C) with some sort of (if A then B else C).

Yes that would be great.

4. Generally, I wonder how hard would it be for all statements to be usable as expressions? Why didn't Swift go that way from the start?

The biggest problem statement is you don’t need to exhaustively specify every outcome:

if cond {
  print(“hello”)
}

whereas in an expression you have to specify what happens in the else.

let say = if cond then “hello” else “goodbye"

unless you go seriously off the deep end:

let say = if cond then “hello”

“say" then becomes an optional, *shudder*

Hello All,

Been sick in bed all day, but decided to try to be productive…

I did a rough draft of a proposal for implementing if expressions and switch expressions based upon the discussions we had here. I have tried to keep the scope of the changes as small as possible, only added one keyword and kept things as similar to the existing language constructs as possible. If anyone wants to help me with this, or has feedback, please let me know,

Thanks,
- Paul

···

On Dec 12, 2015, at 3:51 PM, Paul Ossenbruggen <possen@gmail.com> wrote:

Implied in using the “then", if…then…else would aways require “else" when using “then” similar to how “guard" requires “else”. This will help to make the difference between statements and expressions clear.

let x = If cond then X else Y

is the full form, where “else" can not be omitted.

On Dec 12, 2015, at 12:59 PM, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

On Dec 12, 2015, at 12:37 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. I would really hate to explain to someone when if needs a then and when it doesn't. That's the sort of inconsistency that shouldn't be added lightly.

agreed definitely want to be careful with that. I think with braces meaning statements that differentiation can be made clear. I would certainly start with statements when describing, just as you usually don’t talk about the ternary operator until later.

3. If we can somehow solve all of this, I think I'll be +1 for replacing (A ? B : C) with some sort of (if A then B else C).

Yes that would be great.

4. Generally, I wonder how hard would it be for all statements to be usable as expressions? Why didn't Swift go that way from the start?

The biggest problem statement is you don’t need to exhaustively specify every outcome:

if cond {
  print(“hello”)
}

whereas in an expression you have to specify what happens in the else.

let say = if cond then “hello” else “goodbye"

unless you go seriously off the deep end:

let say = if cond then “hello”

“say" then becomes an optional, *shudder*

I don’t see the current way far

var optSel = "opt2"

let optRes:Int = { switch str{
    
  case "opt1": return 1
  case "opt2": return 2
  default: return 0
    
  } }()

To beauty this maybe operators can come in downgrading eficiency:

let optSel = "opt2"

let optRes = optSel *= [
  
  ("opt1", 1),
  ("opt2", 2)
  
] ?? 3

With (pseudocode):

func *= (left: Any, right: [(Any,Any)]) -> Any? {

  for (rightKey,rightValue) in right{
    
    if rightKey == left {
        
      return rightValue
    }
  }
  
  return nil
}

Or:

let optSel = "opt2"

let optRes = optSel *= [
  
  "opt1": 1,
  "opt2": 2
  
  ] ?? 3

With (just conceptually):

func *= (left: Any, right: Dictionary<Any,Any>) -> Any? {
  
  for rightKey in right.keys(){
    
    if rightKey == left {
      
      return right[rightKey]
    }
  }
  
  return nil
}

···

El 13 des 2015, a les 0:51, Paul Ossenbruggen via swift-evolution <swift-evolution@swift.org> va escriure:

Implied in using the “then", if…then…else would aways require “else" when using “then” similar to how “guard" requires “else”. This will help to make the difference between statements and expressions clear.

let x = If cond then X else Y

is the full form, where “else" can not be omitted.

On Dec 12, 2015, at 12:59 PM, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

On Dec 12, 2015, at 12:37 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. I would really hate to explain to someone when if needs a then and when it doesn't. That's the sort of inconsistency that shouldn't be added lightly.

agreed definitely want to be careful with that. I think with braces meaning statements that differentiation can be made clear. I would certainly start with statements when describing, just as you usually don’t talk about the ternary operator until later.

3. If we can somehow solve all of this, I think I'll be +1 for replacing (A ? B : C) with some sort of (if A then B else C).

Yes that would be great.

4. Generally, I wonder how hard would it be for all statements to be usable as expressions? Why didn't Swift go that way from the start?

The biggest problem statement is you don’t need to exhaustively specify every outcome:

if cond {
  print(“hello”)
}

whereas in an expression you have to specify what happens in the else.

let say = if cond then “hello” else “goodbye"

unless you go seriously off the deep end:

let say = if cond then “hello”

“say" then becomes an optional, *shudder*

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

This is great. Here is my take on it.

Should these be two proposals? One for the if-then-else expression and one
for the switch expression?
I think the proposal would have a better chance if it is focused first on
replacing ?: with if-then-else. It is a very emotional change for a lot of
people. At the end of the proposal you could just briefly mention the
switch expression possibility (I like Al's suggestions.)

If the if then else expression gets approved and implemented then it would
be easier to get a switch expression using the then keyword imo but I do
think we need to include it in the proposal but as a future implementation
and/or possibility.

···

On Saturday, December 12, 2015, Paul Ossenbruggen via swift-evolution < swift-evolution@swift.org> wrote:

Hello All,

Been sick in bed all day, but decided to try to be productive…

I did a rough draft of a proposal for implementing if expressions and
switch expressions based upon the discussions we had here. I have tried to
keep the scope of the changes as small as possible, only added one keyword
and kept things as similar to the existing language constructs as possible.
If anyone wants to help me with this, or has feedback, please let me know,

https://github.com/possen/swift-evolution/blob/master/0020.md

Thanks,
- Paul

On Dec 12, 2015, at 3:51 PM, Paul Ossenbruggen <possen@gmail.com > <javascript:_e(%7B%7D,'cvml','possen@gmail.com');>> wrote:

Implied in using the “then", if…then…else would aways require “else" when
using “then” similar to how “guard" requires “else”. This will help to
make the difference between statements and expressions clear.

let x = If cond then X else Y

is the full form, where “else" can not be omitted.

On Dec 12, 2015, at 12:59 PM, Paul Ossenbruggen <possen@gmail.com > <javascript:_e(%7B%7D,'cvml','possen@gmail.com');>> wrote:

On Dec 12, 2015, at 12:37 PM, Andrey Tarantsov via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

1. I would really hate to explain to someone when *if* needs a *then* and
when it doesn't. That's the sort of inconsistency that shouldn't be added
lightly.

agreed definitely want to be careful with that. I think with braces
meaning statements that differentiation can be made clear. I would
certainly start with statements when describing, just as you usually don’t
talk about the ternary operator until later.

3. If we can somehow solve all of this, I think I'll be +1 for replacing
(A ? B : C) with some sort of (*if* A *then* B *else* C).

Yes that would be great.

4. Generally, I wonder how hard would it be for all statements to be
usable as expressions? Why didn't Swift go that way from the start?

The biggest problem statement is you don’t need to exhaustively specify
every outcome:

if cond {
print(“hello”)
}

whereas in an expression you have to specify what happens in the else.

let say = if cond then “hello” else “goodbye"

unless you go seriously off the deep end:

let say = if cond then “hello”

“say" then becomes an optional, *shudder*

Hi Taras,

I understand your point, if you need to do what you are suggesting, which is multiple statements which, eventually resolve to one result, You would still be able to do that with the existent switch statement. The expression syntax should be thought of as more functional in that you don’t have side effects and other processing in it. It simply flows through and produces one answer as any other expression would.

Another way to think of it, is if you think you should be able to do it with a ternary operator, then you should be able to do it with the proposed solution.

Hi Paul,

what bothers me in your proposal is that you seem to allow only simple expressions. But it is often the case that one needs to have multiple statements to set up the value. For example:

  let data = if connection.valid
    connection.cached_data
  else {
    // generate the data again
}

I have been thinking a bit about how to implement this in connection with the idea of code blocks as closures proposal I have posted earlier (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/002056.html\). Switch is a bit more complicated, but I think that the existing if statement can be easily turned into expression:

   func if_<T>(condition: Bool, then_: (()->T)?, else_: (()->T)?) -> T? {
    var result: T?
    
    if condition {
        result = then_?()
    } else {
        result = else_?()
    }
    
    return result
}

the compiler would then translate all if statements into

   if_(condition, then_: then block, else_: else block)

Your if_ func is interesting, I am going play with this a bit.

if the else block is not present, it will be set to nil. In that case the if expression also evaluates to nil. Now, if the if is used as a statement, the above transformation is sufficient and the return value will be optimised away by the compiler. If the expression form is used (i.e. there is an assignment operation), the compiler will forcefully unwrap the result:

Unless I am misunderstanding your suggestion, I experimented with leaving “else” off resulting in an optional if not all cases are handled. This I think makes it confusing because now you have to deal with an optional, optionals usually mean more conditionals later. I want to know at the end of the expression that my variable was properly set in all cases. It seems like trouble to deal with the possibility that you don’t know the result of the expression at the end of the expression, which is essentially what you have with the nil result and everything after that has to deal with that optional. Doesn’t that mean that all if expressions would return some sort of optional?

let x = if_(condition, then_: then block, else_: else block)!

This way, if else block is absent, the program will crash. A bit of tweaking will also generate a useful error message. I am also sure that it is possible to generate a warning (or even an error) at the compile time without too much effort.

It would be preferred to not have runtime errors or compiler errors to deal with. My proposal, by guaranteeing a result, would not have that issue. This is also why I think I expressions and statements should be different. Trying to make statements into expressions will lead to a lot of complications and will lead to harder to understand programming model. Not saying it is impossible but definitely much more involved.

···

On Dec 13, 2015, at 6:53 AM, Taras Zakharko <taras.zakharko@googlemail.com> wrote:

I think the nice thing about this proposal is that it uses already existing mechanisms in the language and only requires some minimal transformations by the compiler.

The switch expression can be approached in a similar way, but would require more compiler magic.

Best,

Taras

On 13 Dec 2015, at 06:54, Paul Ossenbruggen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello All,

Been sick in bed all day, but decided to try to be productive…

I did a rough draft of a proposal for implementing if expressions and switch expressions based upon the discussions we had here. I have tried to keep the scope of the changes as small as possible, only added one keyword and kept things as similar to the existing language constructs as possible. If anyone wants to help me with this, or has feedback, please let me know,

https://github.com/possen/swift-evolution/blob/master/0020.md

Thanks,
- Paul

On Dec 12, 2015, at 3:51 PM, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

Implied in using the “then", if…then…else would aways require “else" when using “then” similar to how “guard" requires “else”. This will help to make the difference between statements and expressions clear.

let x = If cond then X else Y

is the full form, where “else" can not be omitted.

On Dec 12, 2015, at 12:59 PM, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

On Dec 12, 2015, at 12:37 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. I would really hate to explain to someone when if needs a then and when it doesn't. That's the sort of inconsistency that shouldn't be added lightly.

agreed definitely want to be careful with that. I think with braces meaning statements that differentiation can be made clear. I would certainly start with statements when describing, just as you usually don’t talk about the ternary operator until later.

3. If we can somehow solve all of this, I think I'll be +1 for replacing (A ? B : C) with some sort of (if A then B else C).

Yes that would be great.

4. Generally, I wonder how hard would it be for all statements to be usable as expressions? Why didn't Swift go that way from the start?

The biggest problem statement is you don’t need to exhaustively specify every outcome:

if cond {
  print(“hello”)
}

whereas in an expression you have to specify what happens in the else.

let say = if cond then “hello” else “goodbye"

unless you go seriously off the deep end:

let say = if cond then “hello”

“say" then becomes an optional, *shudder*

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

Thanks for taking the time to put this detailed proposal together.

Regarding the if…then…else expression, it all looks good to me.
I have a few comments on the proposed switch expression:

1)
Is it worth reusing the ‘then’ keyword, instead of colon? If a new keyword is to be added, it’d be good if it wasn’t restricted to only one use. The advantage of using ‘then’ in switch would be to further distinguish the expression from the statement and would fit with the if…then…else expression. The disadvantage is that it adds a little more verbosity (ideally, expressions should be syntactically light-weight).

2)
Having the ‘case’ keyword appear only once, looks a bit odd to me, it gives the impression that it is only associated with the first case.
My preference would be to omit the ‘case’ keyword entirely. In the switch statement it can be helpful, as the cases can run over several lines, therefore the keyword is a handy visual marker for the different cases. The expression for each case should only be one line, so this visual marker shouldn’t be required for switch expressions. Having said that, I understand if people think this is too much of a change. Therefore my suggestion is, either the ‘case’ keyword is omitted from the expression, or it is associated with every case as it currently is with the switch statement.

3)
It might be worth showing an example of binding to associated values in a enum using a switch expression? However, the behaviour should be identical to the switch statement, so this might not be required.

Al

···

On 13 Dec 2015, at 05:54, Paul Ossenbruggen via swift-evolution <swift-evolution@swift.org> wrote:

Hello All,

Been sick in bed all day, but decided to try to be productive…

I did a rough draft of a proposal for implementing if expressions and switch expressions based upon the discussions we had here. I have tried to keep the scope of the changes as small as possible, only added one keyword and kept things as similar to the existing language constructs as possible. If anyone wants to help me with this, or has feedback, please let me know,

https://github.com/possen/swift-evolution/blob/master/0020.md

Thanks,
- Paul

Hi Paul,

thanks for gathering the ideas in a proposal!

You suggested to use if…then…else instead of just using the statement form if … {…} else {…}.
In that case I wonder whether it wouldn’t be better to use „then“ in if-statements as well for consistency:

if condition then {
  …
} else {
  …
}

For switch-expressions I’d just keep the statement syntax as there is only one pair of braces and not one per case. Separating the expressions, for which „then“ had to be introduced in case of the if-expression, is already done nicely by the „case“ keywords.
Here, too, my intent would be to keep the syntax of expression and statement the same for consistency.

Some remarks on the section about alternatives:

The problem with this is that in expressions all cases must be handled. In a statement it is common to not have else. So you could make it an expression if the return value is used. This makes it more complex from both the user's perspective and the compiler perspective. That means that if you were to change a "if" conditional into an expression suddenly you would get an an error if the "else" part was not provided.

I don’t see any problem here. The only rule is that expressions have to have an else clause. This is independent of syntax i.e. whether we uses braces or „then".

Especially for the switch expression I don’t think the standard statement syntax with braces looks bad (as there is only one pair of braces around all cases and not one per case like in the if-statement), at least if you format it a little bit different than in your proposal and drop the unnecessary parentheses:

let color =
    switch enumColor {
    case .Red:
        switch shade {
        case .DarkRed: 0xFFEEEE
        case .LightRed: 0xFF0000
        default: 0xFF1010
        }
    default: 0xFFFFFF
    }

-Thorsten

···

Am 13.12.2015 um 06:54 schrieb Paul Ossenbruggen via swift-evolution <swift-evolution@swift.org>:

Hello All,

Been sick in bed all day, but decided to try to be productive…

I did a rough draft of a proposal for implementing if expressions and switch expressions based upon the discussions we had here. I have tried to keep the scope of the changes as small as possible, only added one keyword and kept things as similar to the existing language constructs as possible. If anyone wants to help me with this, or has feedback, please let me know,

https://github.com/possen/swift-evolution/blob/master/0020.md

Thanks,
- Paul

On Dec 12, 2015, at 3:51 PM, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

Implied in using the “then", if…then…else would aways require “else" when using “then” similar to how “guard" requires “else”. This will help to make the difference between statements and expressions clear.

let x = If cond then X else Y

is the full form, where “else" can not be omitted.

On Dec 12, 2015, at 12:59 PM, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

On Dec 12, 2015, at 12:37 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. I would really hate to explain to someone when if needs a then and when it doesn't. That's the sort of inconsistency that shouldn't be added lightly.

agreed definitely want to be careful with that. I think with braces meaning statements that differentiation can be made clear. I would certainly start with statements when describing, just as you usually don’t talk about the ternary operator until later.

3. If we can somehow solve all of this, I think I'll be +1 for replacing (A ? B : C) with some sort of (if A then B else C).

Yes that would be great.

4. Generally, I wonder how hard would it be for all statements to be usable as expressions? Why didn't Swift go that way from the start?

The biggest problem statement is you don’t need to exhaustively specify every outcome:

if cond {
  print(“hello”)
}

whereas in an expression you have to specify what happens in the else.

let say = if cond then “hello” else “goodbye"

unless you go seriously off the deep end:

let say = if cond then “hello”

“say" then becomes an optional, *shudder*

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

Hi Paul,

what bothers me in your proposal is that you seem to allow only simple expressions. But it is often the case that one needs to have multiple statements to set up the value. For example:

  let data = if connection.valid
    connection.cached_data
  else {
    // generate the data again
}

I have been thinking a bit about how to implement this in connection with the idea of code blocks as closures proposal I have posted earlier (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/002056.html\). Switch is a bit more complicated, but I think that the existing if statement can be easily turned into expression:

   func if_<T>(condition: Bool, then_: (()->T)?, else_: (()->T)?) -> T? {
    var result: T?
    
    if condition {
        result = then_?()
    } else {
        result = else_?()
    }
    
    return result
}

the compiler would then translate all if statements into

   if_(condition, then_: then block, else_: else block)

if the else block is not present, it will be set to nil. In that case the if expression also evaluates to nil. Now, if the if is used as a statement, the above transformation is sufficient and the return value will be optimised away by the compiler. If the expression form is used (i.e. there is an assignment operation), the compiler will forcefully unwrap the result:

let x = if_(condition, then_: then block, else_: else block)!

This way, if else block is absent, the program will crash. A bit of tweaking will also generate a useful error message. I am also sure that it is possible to generate a warning (or even an error) at the compile time without too much effort.

I think the nice thing about this proposal is that it uses already existing mechanisms in the language and only requires some minimal transformations by the compiler.

The switch expression can be approached in a similar way, but would require more compiler magic.

Best,

Taras

···

On 13 Dec 2015, at 06:54, Paul Ossenbruggen via swift-evolution <swift-evolution@swift.org> wrote:

Hello All,

Been sick in bed all day, but decided to try to be productive…

I did a rough draft of a proposal for implementing if expressions and switch expressions based upon the discussions we had here. I have tried to keep the scope of the changes as small as possible, only added one keyword and kept things as similar to the existing language constructs as possible. If anyone wants to help me with this, or has feedback, please let me know,

https://github.com/possen/swift-evolution/blob/master/0020.md

Thanks,
- Paul

On Dec 12, 2015, at 3:51 PM, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

Implied in using the “then", if…then…else would aways require “else" when using “then” similar to how “guard" requires “else”. This will help to make the difference between statements and expressions clear.

let x = If cond then X else Y

is the full form, where “else" can not be omitted.

On Dec 12, 2015, at 12:59 PM, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

On Dec 12, 2015, at 12:37 PM, Andrey Tarantsov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. I would really hate to explain to someone when if needs a then and when it doesn't. That's the sort of inconsistency that shouldn't be added lightly.

agreed definitely want to be careful with that. I think with braces meaning statements that differentiation can be made clear. I would certainly start with statements when describing, just as you usually don’t talk about the ternary operator until later.

3. If we can somehow solve all of this, I think I'll be +1 for replacing (A ? B : C) with some sort of (if A then B else C).

Yes that would be great.

4. Generally, I wonder how hard would it be for all statements to be usable as expressions? Why didn't Swift go that way from the start?

The biggest problem statement is you don’t need to exhaustively specify every outcome:

if cond {
  print(“hello”)
}

whereas in an expression you have to specify what happens in the else.

let say = if cond then “hello” else “goodbye"

unless you go seriously off the deep end:

let say = if cond then “hello”

“say" then becomes an optional, *shudder*

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

I really don't like the "if cond then expr1 else expr2".

1) First of all, it's extremely verbose. It's almost as bad as the SQL construct "case when cond then expr1 else expr2 end".

2) It makes Swift harder to learn. Newcomers will be confused why you sometimes need to use curly braces and why at other times you need to use the "then" keyword.

3) It doesn't help when you want to do multi-line calculations

But there is one good side to this proposal: it nests more naturally than the ternary operator:
"if cond then expr1 else if cond2 then expr2 else expr3"
vs.
"cond ? expr1 : (cond2 ? expr2 : expr3)

The proposed syntax for the switch statement is so confusing that I really don't think it is a good idea.

Why not just allow normal if statements to return values?
I don't see what's so bad about the following:
"let value = if cond {expr1} else {expr2}"

This would also extend to multiple lines:
let value = if cond {
  expr1
} else {
  let something = Object()
  something.doStuff()
  something
}

Jakob

···

On 13 Dec 2015, at 06:54, Paul Ossenbruggen via swift-evolution <swift-evolution@swift.org> wrote:

Hello All,

Been sick in bed all day, but decided to try to be productive…

I did a rough draft of a proposal for implementing if expressions and switch expressions based upon the discussions we had here. I have tried to keep the scope of the changes as small as possible, only added one keyword and kept things as similar to the existing language constructs as possible. If anyone wants to help me with this, or has feedback, please let me know,

https://github.com/possen/swift-evolution/blob/master/0020.md

Thanks,
- Paul

I don't see the "improved" clarity.

Without syntax highlighting, and no indentation to help, it becomes impossible to read. Compare:

let x = if cond then expr1 else expr2
vs
let x = cond ? expr1 : expr2

The former looks just like a random English sentence, the latter is obviously a ternary expression (to my trained eye)

The ternary operator exists in very many languages, and therefore many programmers are familiar with them.

If the purpose is to make the language easier to understand for novice programmers, maybe you could use "when" instead of "if", for example:

let x = when cond then expr1 else expr2

This has several advantages:

1) The difference between statements and expressions becomes trivial:
- "if" is a statement
- "when" is an expression

2) it becomes easier to google. "swift when" might get better results compared to "swift ?" or "swift if"

3) people familiar with SQL will recognise the functional WHEN expression

4) Of course it is even longer, but at this point, who cares.

Jakob

···

On 13 Dec 2015, at 20:31, Paul Ossenbruggen <possen@gmail.com <mailto:possen@gmail.com>> wrote:

I really don't like the "if cond then expr1 else expr2".

1) First of all, it's extremely verbose. It's almost as bad as the SQL construct "case when cond then expr1 else expr2 end”.

Yeah it adds a few characters overall. What used to be 2 chars now takes 10. Clarity is preferred though by many. I head frequently people telling users to never use ternary operators because they are confusing to read.