Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permit ternary operation with int? and double operands #881

Open
gafter opened this issue Sep 5, 2017 · 17 comments
Open

Permit ternary operation with int? and double operands #881

gafter opened this issue Sep 5, 2017 · 17 comments

Comments

@gafter
Copy link
Member

gafter commented Sep 5, 2017

We would like to change the spec for #33 so that this proposed feature also permits the following:

int? ni = 1;
double d = 4;
bool c = true;
var x1 = c ? ni : d;

This is currently an error because there is no implicit conversion between int? and double in either direction.

@gafter gafter added the Spec label Sep 5, 2017
@gafter gafter added this to the 7.X candidate milestone Sep 5, 2017
@gafter gafter self-assigned this Sep 5, 2017
@bondsbw
Copy link

bondsbw commented Sep 5, 2017

To clarify, is the type of x1 intended to be double? (as the greatest common type) or int? due to flow analysis?

@iam3yal
Copy link
Contributor

iam3yal commented Sep 6, 2017

@bondsbw yes x1 is intended to be double? as it can't be int? because there's no conversion between double to int or double? to int? and there's no flow analysis done here so the type of var is always one of the types you had to type yourself so the only option left here is double?.

To sums this up, this works:

int? ni = 1;
double d = 4;
double? x1 = ni;
double? x2 = d;

@MgSam
Copy link

MgSam commented Sep 6, 2017

@gafter I assume this implies lots of other conversions as well?

  • short? and double
  • short? and int
  • int? and long
  • etc.

@bondsbw
Copy link

bondsbw commented Sep 6, 2017

How does this play out considering union/intersection types (#399)?

This proposal advocates that the result of a ternary expression is a union type, because double? is equivalent to int? | double.

But as @HaloFour commented here, an intersection type seems reasonable as well. You should only be able to perform operations on the result which are common to both types. The result of var animal = condition ? new Dog() : new Cat() should not allow animal.Bark() since it could be a Cat.

EDIT: after some thought, what I described in the second paragraph is the union type, not intersection.

@MgSam
Copy link

MgSam commented Sep 6, 2017

I'd say ternary should never make implicitly a union/intersection type but require you to instead be explicit. Implicit behavior is bound to lead to confusion and ambiguity for precisely the reasons you illustrate.

All academic, of course, since the team hasn't shown any interest in the feature.

@bondsbw
Copy link

bondsbw commented Sep 6, 2017

All academic, of course, since the team hasn't shown any interest in the feature.

Perhaps, but implementing this proposal could impact future plans.

@DavidArno
Copy link

DavidArno commented Sep 7, 2017

Definitely with @bondsbw here (and presumably, by implication, @HaloFour too). Such changes as proposed here should be deferred until after any work (or formal rejection) of union and intersection types is complete.

@MgSam
Copy link

MgSam commented Sep 7, 2017

@DavidArno So stop a nice feature we could have in a few months for the remote possibility of a feature in 5 or 10 years? Sounds like paralysis through analysis.

@DavidArno
Copy link

@MgSam,

That really depends on whether one views this as a "nice feature" or not. From my perspective it's a minor niche feature that absolutely should not take priority over a good implementation of union and intersection types. If this change affects you though, and you have no interest in unions and intersections, you'll likely have a very different view on priorities.

@HaloFour
Copy link
Contributor

HaloFour commented Sep 7, 2017

This proposal only affects a select view value types. I can't imagine that intersection types, if they are ever implemented, will ever support value types, so I'm all for this proposal being implemented today.

@MgSam
Copy link

MgSam commented Sep 7, 2017

@DavidArno Questions/complaints about the current inability of the ternary operator to handle cases like this (and null propagation) are extremely common on StackOverflow and elsewhere. And I don't know about you but I write ternary operators literally every single day. Granted most of those won't benefit from this sub-feature, but the closer the operator gets to "it just works like you'd expect it to" the better.

@gafter
Copy link
Member Author

gafter commented Sep 23, 2017

How does this play out considering union/intersection types (#399)?

How would you suggest it should play out? Please explain what implications you believe we should be considering, considering that we may or may not ever do them.

@bondsbw
Copy link

bondsbw commented Sep 28, 2017

@gafter I believe I was mistaken that there is a conflict (and I edited that comment).

I'd still like to flesh it out a bit. Generalizing the original example:

int? ni = ...;
double d = ...;
bool c = true;
var x1 = c ? ni : d;

As stated above for #399, x1 would have the union type int? | double. This would be the union set of int? and double.

int? (for practical purposes) is the set

  • -2147483648
  • ...
  • -1
  • 0
  • 1
  • ...
  • 2147483647
  • null

and double is the set of

  • Positive and negative zero.
  • Positive and negative infinity.
  • Not-a-Number value (NaN).
  • The finite set of nonzero values between -1.79769313486232E+308 and 1.79769313486232E+308 which have 52 significand bits and 11 exponent bits (and a sign bit).

Since double contains all values in int, then int? | double is the set of values in double plus the value null... in other words, double?.

So the issue is the idea that int? | double automagically becomes double?. (Not saying that's bad in any way, but just thinking about implications to the design.)

@bondsbw
Copy link

bondsbw commented Sep 28, 2017

Consider another case:

sbyte? sb = ...;
byte b = ...;
bool c = true;
var x2 = c ? sb : b;

x2 has the type sbyte? | byte. There is not an exact equivalent type that is built in. I think the closest superset is short?. So does x2 have the type sbyte? | byte or short??

EDIT: separated into another comment

@MadsTorgersen MadsTorgersen modified the milestones: 7.X candidate, 8.0 candidate Oct 9, 2017
@gafter
Copy link
Member Author

gafter commented Sep 6, 2018

The spec has been changed by #1806 as requested.

So this would now be included in the championed issue #33

@gafter gafter modified the milestones: 8.0 candidate, 8.X candidate Apr 29, 2019
@gafter
Copy link
Member Author

gafter commented Aug 28, 2019

This should be done (if at all) at the same time as #2473 and #2460.

@gafter gafter modified the milestones: 8.X candidate, 9.0 candidate Aug 28, 2019
@gafter
Copy link
Member Author

gafter commented Aug 28, 2019

See also #881

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants