www.digitalmars.com         C & C++   DMDScript  

D - double to int conversion

reply "Derek Parnell" <Derek.Parnell psyc.ward> writes:
Walter,
as I understand it, I can get this message "constructor this overloads Foo  
(int x) and Foo (double x) both match argument list for this" when I have  
defined ...

    this(int x) { ... }
    this(double x) { ... }

and I then try to do this ...

    Foo a = new Foo('D');

Which means that the compiler has decided that the literal character 'D'  
could be either an integer or a double and therefore the coder must make  
the call explicit.

So my question is - how often have you even seen a coder write a literal  
character down to mean a double (floating point) value?

I would have thought that the overwhelming practice is that a literal  
character represents an integer and if a coder really needs it to be a  
double they would explicitly cast it as such...

    double x = cast(double)'D';

With the current D implementation, the coder nearly always has to do more  
work now than they used to do (for the same idiom) in  
C/C++/Java/whatever...

-- 
Derek
Apr 01 2004
parent reply "Walter" <walter digitalmars.com> writes:
"Derek Parnell" <Derek.Parnell psyc.ward> wrote in message
news:opr5tcocfiu2m3b2 news.digitalmars.com...
 Walter,
 as I understand it, I can get this message "constructor this overloads Foo
 (int x) and Foo (double x) both match argument list for this" when I have
 defined ...

     this(int x) { ... }
     this(double x) { ... }

 and I then try to do this ...

     Foo a = new Foo('D');

 Which means that the compiler has decided that the literal character 'D'
 could be either an integer or a double and therefore the coder must make
 the call explicit.

 So my question is - how often have you even seen a coder write a literal
 character down to mean a double (floating point) value?

 I would have thought that the overwhelming practice is that a literal
 character represents an integer and if a coder really needs it to be a
 double they would explicitly cast it as such...

     double x = cast(double)'D';

 With the current D implementation, the coder nearly always has to do more
 work now than they used to do (for the same idiom) in
 C/C++/Java/whatever...
You make a good argument for that case. However, I decided against the C++ notion of 'best fit' because the combination of all the best fit rules is very confusing. There are 3 levels of matching in D (rather than an arbitrarilly large number with several special case rules tossed in) which are 1) exact match 2) match with implicit conversions and 3) no match. Sure, in D, you'll have a cast or two extra once in a while, but the payoff is a clear set of simple rules, rather than a morass of confusing, subtle ones. I will also argue that a function with int and double overloads that gets passed a character literal perhaps is not designed right, though I could be wrong as I don't know the details of your specific application.
Apr 02 2004
next sibling parent reply "Derek Parnell" <not available.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:c4jafo$96k$1 digitaldaemon.com...
 "Derek Parnell" <Derek.Parnell psyc.ward> wrote in message
 news:opr5tcocfiu2m3b2 news.digitalmars.com...
 Walter,
 as I understand it, I can get this message "constructor this overloads
Foo
 (int x) and Foo (double x) both match argument list for this" when I
have
 defined ...

     this(int x) { ... }
     this(double x) { ... }

 and I then try to do this ...

     Foo a = new Foo('D');

 Which means that the compiler has decided that the literal character 'D'
 could be either an integer or a double and therefore the coder must make
 the call explicit.

 So my question is - how often have you even seen a coder write a literal
 character down to mean a double (floating point) value?

 I would have thought that the overwhelming practice is that a literal
 character represents an integer and if a coder really needs it to be a
 double they would explicitly cast it as such...

     double x = cast(double)'D';

 With the current D implementation, the coder nearly always has to do
more
 work now than they used to do (for the same idiom) in
 C/C++/Java/whatever...
You make a good argument for that case. However, I decided against the C++ notion of 'best fit' because the combination of all the best fit rules is very confusing. There are 3 levels of matching in D (rather than an arbitrarilly large number with several special case rules tossed in) which are 1) exact match 2) match with implicit conversions and 3) no match.
Sure,
 in D, you'll have a cast or two extra once in a while, but the payoff is a
 clear set of simple rules, rather than a morass of confusing, subtle ones.
Thanks. However I'm not actually talking about the rules for matching function signatures. All I'm trying to say is that a character literal is an integer and is never a floating point value. Okay, let's have a straw poll - hands up all the people who have coded a character literal in order to represent a floating point value. Hmmmm...okay then. Hands up all the people who have ever been confused or uncertain about whether a character literal is an interger or floating point value. Walter, I'm not talking about Foo(int) and Foo(double)... I'm just saying that every coder that I've ever talked with, just assumes that a character literal represents an integer value and never represents a floating point value.
 I will also argue that a function with int and double overloads that gets
 passed a character literal perhaps is not designed right, though I could
be
 wrong as I don't know the details of your specific application.
And because you could be wrong, is the main reason to allow the CODER to decide if it worthwhile or not, not the language designer. But back to your discussion about matching int and double. Because I can't have ... this(int x){...} AND this(double x){...} I've had to resort to this workaround... this(double x) { if ( (cast(int)x) == x) { < ...do integer processing...> } else { <... do floating point processing...> } } Just so I could write in the application ... Foo a = new Foo('D'); Crazy, eh?! So if you could see your way to making the (alredy assumed by thousands of coders) rule that a character literal represents an 'int' then you have made coding in D just a little bit simplier. And in terms of consistancy, if the ctor's above refuse to handle character literals, why does this work ... int x = 'a'; To be consistant, the D compiler would also have to say that because 'a' might be either an integer OR a double, it can't blindly go implictly converting the 'a' to an integer. That's what its doing for the ctor case! Either that or start allowing .... int x = 1.23; because it obviously does know how to convert a floating point into an integer because ... int x = (cast (int)1.23); works just fine as a built-in conversion. -- Derek
Apr 02 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Derek Parnell wrote:

Thanks. However I'm not actually talking about the rules for matching
function signatures. All I'm trying to say is that a character literal is an
integer and is never a floating point value.  Okay, let's have a straw
poll - hands up all the people who have coded a character literal in order
to represent a floating point value.   Hmmmm...okay then. Hands up all the
people who have ever been confused or uncertain about whether a character
literal is an interger or floating point value.

Walter, I'm not talking about Foo(int) and Foo(double)... I'm just saying
that every coder that I've ever talked with, just assumes that a character
literal represents an integer value and never represents a floating point
value.
  
Actually I assume that a character literal represents a byte.
And because you could be wrong, is the main reason to allow the CODER to
decide if it worthwhile or not, not the language designer.
  
But the programmer has the option with casting, its just that in most cases they are probably wrong. All the programmer has to do is explicitly say what they mean.
But back to your discussion about matching int and double. Because I can't
have ...

   this(int x){...} AND this(double x){...} I've had to resort to this
workaround...
  
Why not?
 this(double x)
 {
    if ( (cast(int)x) == x)
    {
      < ...do integer processing...>
    }
    else
    {
      <... do floating point processing...>
    }
 }
  
This only archives loss of information.
Just so I could write in the application ...

   Foo a = new Foo('D');

  
Why not? this(double d) { printf("d\n");} this(int i) { printf("i\n");} this(char c) { this((int)c);}
Crazy, eh?! So if you could see your way to making the (alredy assumed by
thousands of coders) rule that a character literal represents an 'int' then
you have made coding in D just a little bit simplier.
  
In my opinion this makes things more difficult. How often do you need to convert a character to integer? C coders also assume that they need to delete every object they create manually, so what's your point?
And in terms of consistancy, if the ctor's above refuse to handle character
literals, why does this work ...

  int x = 'a';
  
Here it's obvious what the programmer means so why write the word (int) twice in the same sentence. With overloading, its often much more difficult to determine what the programmer means because the definition part of the code is somewhere else.
To be consistant, the D compiler would also have to say that because 'a'
might be either an integer OR a double, it can't blindly go implictly
converting the 'a' to an integer. That's what its doing for the ctor case!
Either that or start allowing ....

  int x = 1.23;
  

because it obviously does know how to convert a floating point into an
integer because ...

  int x = (cast (int)1.23);

works just fine as a built-in conversion.
And so it should behave this way. "int x = 1.23" is obviously a programming error. IMHO the language should try to help out the programmer (where possible) by making obvious semantic errors, syntactical ones. -- -Anderson: http://badmama.com.au/~anderson/
Apr 02 2004
parent reply "Derek Parnell" <not available.com> writes:
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:c4k13a$1dps$1 digitaldaemon.com...
 Derek Parnell wrote:

Thanks. However I'm not actually talking about the rules for matching
function signatures. All I'm trying to say is that a character literal is
an
integer and is never a floating point value.  Okay, let's have a straw
poll - hands up all the people who have coded a character literal in
order
to represent a floating point value.   Hmmmm...okay then. Hands up all
the
people who have ever been confused or uncertain about whether a character
literal is an interger or floating point value.

Walter, I'm not talking about Foo(int) and Foo(double)... I'm just saying
that every coder that I've ever talked with, just assumes that a
character
literal represents an integer value and never represents a floating point
value.
Actually I assume that a character literal represents a byte.
And is a byte an integer or a floating point value? I think its an integer. I never think that a byte is a floating point value. Notice that I'm NOT talking about data storage formats such as 'int' and 'double' (yet), but 'integer' and 'floating point' VALUES.
And because you could be wrong, is the main reason to allow the CODER to
decide if it worthwhile or not, not the language designer.
But the programmer has the option with casting, its just that in most cases they are probably wrong. All the programmer has to do is explicitly say what they mean.
But with character literals we DO NOT have the option of casting - we are forced to cast it to the obvious 'int'. Foo x = new Foo('a'); // FAILS Foo y = new Foo(cast(int)'a'); // Works. But when is the 'a' ever a floating point value? It is always an integer value. Therefore, IMNSHO, D should implictly convert it to an int and not even bother trying to convert it a double.
But back to your discussion about matching int and double. Because I
can't
have ...

   this(int x){...} AND this(double x){...} I've had to resort to this
workaround...
Why not?
Because the D complier spits out an error message. And I quote "constructor this overloads Foo (int a) and Foo (double a) both match argument list for this"
 this(double x)
 {
    if ( (cast(int)x) == x)
    {
      < ...do integer processing...>
    }
    else
    {
      <... do floating point processing...>
    }
 }
This only archives loss of information.
What?! How could you possibly know what the difference between the "integer processing" and "floating point processing" is, to say that information is being lost? I honestly do not understand your remark.
Just so I could write in the application ...

   Foo a = new Foo('D');
Why not? this(double d) { printf("d\n");} this(int i) { printf("i\n");} this(char c) { this((int)c);}
Thank you very very much. This is the answer to my fuzzy thinking. You have made it clear to me at last. I had just assumed that D thought that a character literal was an 'int' when (of course I see now) it is a 'char'. Now I can sleep tonight ;-)
Crazy, eh?! So if you could see your way to making the (alredy assumed by
thousands of coders) rule that a character literal represents an 'int'
then
you have made coding in D just a little bit simplier.
In my opinion this makes things more difficult. How often do you need to convert a character to integer?
I forgot that a 'char' is a different beast to an 'int'. I'm back on the righteous path now ;-)
 C coders also assume that they need to delete every object they create
 manually, so what's your point?
I'm still a newbie with heaps of baggage to unlearn. Thanks for helping me. -- Derek
Apr 02 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
Derek Parnell wrote:

And is a byte an integer or a floating point value? I think its an integer.
I never think that a byte is a floating point value. Notice that I'm NOT
talking about data storage formats such as 'int' and 'double' (yet), but
'integer' and 'floating point' VALUES.
  
Right-o
But with character literals we DO NOT have the option of casting - we are
forced to cast it to the obvious 'int'.

   Foo x = new Foo('a'); // FAILS
   Foo y = new Foo(cast(int)'a'); // Works.

But when is the 'a' ever a floating point value? It is always an integer
value. Therefore, IMNSHO, D should implictly convert it to an int and not
even bother trying to convert it a double.
  
a is a character.
Because the D complier spits out an error message. And I quote "constructor
this overloads Foo (int a) and Foo (double a) both match argument list for
this"
  
Humm, your right, wrong error message. Obviously the compiler is converting character to an integer before running that test. I think you shouldn't be allowed to actually pass a character into a function that is meant to do integer stuff, you most-probably meant that character for something else. If you do need it, it, should be cast.
this(double x)
{
   if ( (cast(int)x) == x)
   {
     < ...do integer processing...>
   }
   else
   {
     <... do floating point processing...>
   }
}


      
This only archives loss of information.
What?! How could you possibly know what the difference between the "integer processing" and "floating point processing" is, to say that information is being lost? I honestly do not understand your remark.
Sorry I was thinking 64-bit integers (dam C++).
Why not?
this(double d) { printf("d\n");}
this(int i) { printf("i\n");}
this(char c) { this((int)c);}
    
Thank you very very much. This is the answer to my fuzzy thinking. You have made it clear to me at last. I had just assumed that D thought that a character literal was an 'int' when (of course I see now) it is a 'char'. Now I can sleep tonight ;-) I forgot that a 'char' is a different beast to an 'int'. I'm back on the righteous path now ;-)
I'm happy to hear that. -- -Anderson: http://badmama.com.au/~anderson/
Apr 02 2004
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Derek Parnell" <not available.com> wrote in message
news:c4jvgu$1a8s$1 digitaldaemon.com...
 Walter, I'm not talking about Foo(int) and Foo(double)... I'm just saying
 that every coder that I've ever talked with, just assumes that a character
 literal represents an integer value and never represents a floating point
 value.
The underlying thing going on here is that the C integral promotion rules will promote a char value to a floating point value. Changing those rules is tempting, but will cause too many subtle behavior differences from C/C++. I tried to avoid subtle behavior differences, especially in the arena of things like promotion rules, because it can be really hard to notice them in complex expressions which abound in C/C++. Tripping an explicit error in D is preferable because it's at least obvious that there's something that needs adjusting.
 I will also argue that a function with int and double overloads that
gets
 passed a character literal perhaps is not designed right, though I could
be
 wrong as I don't know the details of your specific application.
And because you could be wrong, is the main reason to allow the CODER to decide if it worthwhile or not, not the language designer.
D aims to make what is generally considered to be good programming practice easier to write, while making what is generally considered to be bad practice harder to write (so it stands out). A poorly designed language makes good code hard to write and bad code easy to write.
 But back to your discussion about matching int and double. Because I can't
 have ...
    this(int x){...} AND this(double x){...}
You can have it by adding: this(char c) { ... }
 Crazy, eh?! So if you could see your way to making the (alredy assumed by
 thousands of coders) rule that a character literal represents an 'int'
then
 you have made coding in D just a little bit simplier.
Buried in C is also the rule that chars get implicitly promoted to floating point values.
 And in terms of consistancy, if the ctor's above refuse to handle
character
 literals, why does this work ...

   int x = 'a';

 To be consistant, the D compiler would also have to say that because 'a'
 might be either an integer OR a double, it can't blindly go implictly
 converting the 'a' to an integer. That's what its doing for the ctor case!
In the initialization case, there is no ambiguity, so there is no special case rule the language is applying. The following also works in C and D: double d = 'a';
Apr 02 2004
parent reply "Derek Parnell" <not available.com> writes:
Thank you Walter. You have given excellent answers here. I can understand
your point of view and rationale for D's behaviour. Who knows, maybe someday
I might even come around to sharing this POV too ;-)


"Walter" <walter digitalmars.com> wrote in message
news:c4k5jp$1mpv$1 digitaldaemon.com...
 "Derek Parnell" <not available.com> wrote in message
 news:c4jvgu$1a8s$1 digitaldaemon.com...
 Walter, I'm not talking about Foo(int) and Foo(double)... I'm just
saying
 that every coder that I've ever talked with, just assumes that a
character
 literal represents an integer value and never represents a floating
point
 value.
The underlying thing going on here is that the C integral promotion rules will promote a char value to a floating point value. Changing those rules
is
 tempting, but will cause too many subtle behavior differences from C/C++.
I
 tried to avoid subtle behavior differences, especially in the arena of
 things like promotion rules, because it can be really hard to notice them
in
 complex expressions which abound in C/C++. Tripping an explicit error in D
 is preferable because it's at least obvious that there's something that
 needs adjusting.

 I will also argue that a function with int and double overloads that
gets
 passed a character literal perhaps is not designed right, though I
could
 be
 wrong as I don't know the details of your specific application.
And because you could be wrong, is the main reason to allow the CODER to decide if it worthwhile or not, not the language designer.
D aims to make what is generally considered to be good programming
practice
 easier to write, while making what is generally considered to be bad
 practice harder to write (so it stands out). A poorly designed language
 makes good code hard to write and bad code easy to write.


 But back to your discussion about matching int and double. Because I
can't
 have ...
    this(int x){...} AND this(double x){...}
You can have it by adding: this(char c) { ... }
 Crazy, eh?! So if you could see your way to making the (alredy assumed
by
 thousands of coders) rule that a character literal represents an 'int'
then
 you have made coding in D just a little bit simplier.
Buried in C is also the rule that chars get implicitly promoted to
floating
 point values.

 And in terms of consistancy, if the ctor's above refuse to handle
character
 literals, why does this work ...

   int x = 'a';

 To be consistant, the D compiler would also have to say that because 'a'
 might be either an integer OR a double, it can't blindly go implictly
 converting the 'a' to an integer. That's what its doing for the ctor
case!
 In the initialization case, there is no ambiguity, so there is no special
 case rule the language is applying. The following also works in C and D:

     double d = 'a';
Apr 02 2004
parent "Walter" <walter digitalmars.com> writes:
"Derek Parnell" <not available.com> wrote in message
news:c4kpcn$2k7h$1 digitaldaemon.com...
 Thank you Walter. You have given excellent answers here. I can understand
 your point of view and rationale for D's behaviour. Who knows, maybe
someday
 I might even come around to sharing this POV too ;-)
It's unreasonable to expect everyone to agree with me on every point, but I am glad I was able to explain the rationale in a lucid manner.
Apr 02 2004
prev sibling parent reply Matthias Becker <Matthias_member pathlink.com> writes:
You make a good argument for that case. However, I decided against the C++
notion of 'best fit' because the combination of all the best fit rules is
very confusing. There are 3 levels of matching in D (rather than an
arbitrarilly large number with several special case rules tossed in) which
are 1) exact match 2) match with implicit conversions and 3) no match. Sure,
in D, you'll have a cast or two extra once in a while, but the payoff is a
clear set of simple rules, rather than a morass of confusing, subtle ones.
I proved that dmd doesn't follow this rule (haven't tested with the current version. I did it with 0.7x, can't remember the exact version). So have you fixed it? I didn't want you to do so. Damn. (The thread was called "A bug that I like", if I remember right)
Apr 04 2004
next sibling parent "Walter" <walter digitalmars.com> writes:
"Matthias Becker" <Matthias_member pathlink.com> wrote in message
news:c4oftn$2200$1 digitaldaemon.com...
 I proved that dmd doesn't follow this rule (haven't tested with the
current
 version. I did it with 0.7x, can't remember the exact version). So have
you
 fixed it? I didn't want you to do so. Damn.

 (The thread was called "A bug that I like", if I remember right)
I don't remember that particular problem. If it is in the bug database, however, it will remain there until it gets fixed.
Apr 04 2004
prev sibling parent J C Calvarese <jcc7 cox.net> writes:
Matthias Becker wrote:
You make a good argument for that case. However, I decided against the C++
notion of 'best fit' because the combination of all the best fit rules is
very confusing. There are 3 levels of matching in D (rather than an
arbitrarilly large number with several special case rules tossed in) which
are 1) exact match 2) match with implicit conversions and 3) no match. Sure,
in D, you'll have a cast or two extra once in a while, but the payoff is a
clear set of simple rules, rather than a morass of confusing, subtle ones.
I proved that dmd doesn't follow this rule (haven't tested with the current version. I did it with 0.7x, can't remember the exact version). So have you fixed it? I didn't want you to do so. Damn. (The thread was called "A bug that I like", if I remember right)
I don't know that Walter changed anything. Perhaps he already fixed the bug before he found saw your post. I think I found your earlier post (http://www.digitalmars.com/drn-bin/wwwnews?D/24040) and Walter's reply (http://www.digitalmars.com/drn-bin/wwwnews?D/24465). I got the same error message that Walter seemed to get: fn_ovrld.d(17): function func overloads void(Foo foo) and void(Bar bar) both match argument list for func I tested it with DMD 0.81. (I guess it's time for me install DMD 0.82.) -- Justin http://jcc_7.tripod.com/d/
Apr 04 2004