April 26, 2013
On 4/26/2013 1:59 PM, Diggory wrote:
> The actual value shouldn't be taken into
> account when determining which overload to call, only the type should matter,

D has an interesting feature called VRP (value range propagation), where implicit conversion very much depends on the value. For example:

ubyte b;
b = 100;    // ok
b = 300;    // error

This has been very successful in reducing the noise of having to insert casts all over the place.

For:

enum e = 1;

then e is a value that is known to be one. Hence VRP applies, and it can be implicitly cast to bool, ubyte, short, etc. For:

static e = 1;

the compiler cannot assume that e is always 1, hence e is treated as an int that could hold any value. Hence, it cannot be implicitly cast to bool, ubyte, short, etc.


> Ideally such an implicit conversion would only apply if it was the only possible valid implicit conversion,

This was how D originally worked. However, it produced a list of foolish errors, and a lot of complaints. The current scheme attempts to resolve ambiguities by doing a "partial ordering" (described elsewhere in this thread). This has been very successful.

To make use of overloading, there's no avoiding understanding this. A program that breaks due to different overloadings of:

    enum e = 1;
    static x = 1;

is misusing overloading just like one that breaks on different overloads of:

    enum e = 30000;
    static x = 40000;

I.e.:

    void foo(short) { ... back up my files ... }
    void foo(long) { ... launch nuclear missiles ... }

is a bad program.
April 26, 2013
On 4/26/2013 1:59 PM, Andrej Mitrovic wrote:
> On 4/26/13, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
>> An even better example:
>
> import std.stdio;
>
> void foo(bool x) { writeln("1"); }
> void foo(long x) { writeln("2"); }
>
> void main()
> {
>      foo(1);  // "1"
>      foo(false ? 2 : 1);  // "2"
> }
>
> Kill it with fire.

How about this one:

import std.stdio;

void foo(short x) { writeln("1"); }
void foo(long x) { writeln("2"); }

void main()
{
     foo(30000);  // "1"
     foo(false ? 40000 : 30000);  // "2"
}
April 26, 2013
On Friday, 26 April 2013 at 21:32:32 UTC, Tove wrote:
> On Friday, 26 April 2013 at 21:01:17 UTC, Brian Schott wrote:
>> On Friday, 26 April 2013 at 06:01:27 UTC, Walter Bright wrote:
> Sometimes due to bad coding standards I´m forced to write...
> if((.....long expression with not immediately apparent operator precedence)!=0)

I assume you are doing C or C++. Under the preprocessor, why do not #define a ifnonzero() and a ifzero() macro, if that bothers you so much? (also works for testing against NULL).

In D, it is less possible to do so (curse of lacking processor...). Or maybe it is and I am missing it.

April 26, 2013
Tove:

> Sometimes due to bad coding standards I´m forced to write...
> if((.....long expression with not immediately apparent operator precedence)!=0)
> ... absolutely appalling, kills readability with extra () etc.

I think here people are not asking to disallow that. A 0 and 1 can be false and true in a boolean evaluation context even if they don't implicitly cast to int in other situations.

Bye,
bearophile
April 26, 2013
On Friday, April 26, 2013 14:14:55 Walter Bright wrote:
> On 4/26/2013 12:37 PM, Jonathan M Davis wrote:
> > There's nothing whatsoever about bool that
> > makes sense as an integral type.
> 
> This is where our perspectives sharply diverge. A bool is a 1 bit integer type. Take a look at this, for example:
> 
> http://d.puremagic.com/issues/show_bug.cgi?id=9963
> 
> Mathematically, they behave like 1 bit integers and are useful that way.

Sure, it may be useful sometimes to have code that treats true as 1 and false as 0 for math, but I'd argue for casting being required for it, and in a large number of cases, casting would be required already due to the fact that it would be a narrowing conversion. But it seems very wrong to me that foo(1) would call a bool overload or that "foo" ~ true would compile. There have been a number of posts over time discussing bugs caused by that behavior being legal. I don't think that it's a huge problem, but I do think that it's a problem. However, we are clearly coming from very different points of view here.

- Jonathan M Davis
April 26, 2013
On Friday, 26 April 2013 at 21:37:14 UTC, Walter Bright wrote:
> On 4/26/2013 1:59 PM, Andrej Mitrovic wrote:
>> On 4/26/13, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
>>> An even better example:
>>
>> import std.stdio;
>>
>> void foo(bool x) { writeln("1"); }
>> void foo(long x) { writeln("2"); }
>>
>> void main()
>> {
>>     foo(1);  // "1"
>>     foo(false ? 2 : 1);  // "2"
>> }
>>
>> Kill it with fire.
>
> How about this one:
>
> import std.stdio;
>
> void foo(short x) { writeln("1"); }
> void foo(long x) { writeln("2"); }
>
> void main()
> {
>      foo(30000);  // "1"
>      foo(false ? 40000 : 30000);  // "2"
> }

We all know that short and long are integer numerics, however most of us do not think of bool as being a 1 bit integer type. We expect values of 'true' and 'false' because D has explicit 'true' and 'false' values, which presumably are there because 1 and 0 which are not the same thing as 'true' and 'false', otherwise there would be no need for 'true' and 'false'.

--rt
April 27, 2013
On Friday, 26 April 2013 at 21:34:44 UTC, Walter Bright wrote:
>     void foo(short) { ... back up my files ... }
>     void foo(long) { ... launch nuclear missiles ... }
>
> is a bad program.

The government of North Korea would probably be perfectly happy with this program, but then again, that's a bad government.
April 27, 2013
On Friday, April 26, 2013 14:34:45 Walter Bright wrote:
> D has an interesting feature called VRP (value range propagation), where implicit conversion very much depends on the value.

VRP is a fantastic feature, but I think that it's coming back to bite us somewhat if foo(1) calls an overload which takes bool.

- Jonathan M Davis
April 27, 2013
On Fri, Apr 26, 2013 at 08:05:45PM -0400, Jonathan M Davis wrote:
> On Friday, April 26, 2013 14:34:45 Walter Bright wrote:
> > D has an interesting feature called VRP (value range propagation), where implicit conversion very much depends on the value.
> 
> VRP is a fantastic feature, but I think that it's coming back to bite us somewhat if foo(1) calls an overload which takes bool.
[...]

Does VRP work only with literals, or does it work with general variables (by inferring from, say, if-conditions)?

	void func(int i) {
		ubyte b;
		if (i >= 0 && i < 256) {
			b = i;		// OK without cast?
		}
		...
	}


T

-- 
That's not a bug; that's a feature!
April 27, 2013
On Friday, 26 April 2013 at 19:22:51 UTC, Walter Bright wrote:
> I remember once a language that tried to define true and false as something other than 1 and 0. It was horrible.

Don't need to look far away. Most shell do that.