www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - 1 matches bool, 2 matches long

reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
This question has first appeared on D.learn:

   http://forum.dlang.org/post/vlosugoeuobjrdfaeegk forum.dlang.org

A simple program:

import std.stdio;

void foo(bool b)
{
     writeln("bool");
}

void foo(long l)
{
     writeln("long");
}

void main()
{
     foo(1);
     foo(2);
}

The program calls two separate foo() overloads for 1 and 2:

bool
long

According to the language spec, both overloads match the int argument by 
"implicit conversion" as described under "Function Overloading" here:

   http://dlang.org/function.html

Then, the overload must be resolved by partial ordering: "If two or more 
functions have the same match level, then partial ordering is used to 
try to find the best match. Partial ordering finds the most specialized 
function."

Is bool more specialized than long or is this a bug? Intuitively, both 
should match the 'long' overload. It feels like there should at least be 
ambiguity.

Ali
Apr 25 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/25/2013 11:05 PM, Ali Çehreli wrote:
 ...

 Is bool more specialized than long or is this a bug? Intuitively, both
 should match the 'long' overload.
bool is more specialized than long; you can pass any bool argument as a long argument, but not vice versa.
 It feels like there should at least be ambiguity.
 ...
This would be an enhancement. (A possible rule to add would be that literal-level conversions cannot influence the chosen overload.)
Apr 25 2013
prev sibling next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-04-25, 23:05, Ali =C3=87ehreli wrote:

 This question has first appeared on D.learn:

    http://forum.dlang.org/post/vlosugoeuobjrdfaeegk forum.dlang.org

 A simple program:

 import std.stdio;

 void foo(bool b)
 {
      writeln("bool");
 }

 void foo(long l)
 {
      writeln("long");
 }

 void main()
 {
      foo(1);
      foo(2);
 }

 The program calls two separate foo() overloads for 1 and 2:

 bool
 long

 According to the language spec, both overloads match the int argument =
by =
 "implicit conversion" as described under "Function Overloading" here:

    http://dlang.org/function.html

 Then, the overload must be resolved by partial ordering: "If two or mo=
re =
 functions have the same match level, then partial ordering is used to =
=
 try to find the best match. Partial ordering finds the most specialize=
d =
 function."

 Is bool more specialized than long or is this a bug? Intuitively, both=
=
 should match the 'long' overload. It feels like there should at least =
be =
 ambiguity.
For what it's worth, this is ambiguous in C++. -- = Simen
Apr 25 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
 Is bool more specialized than long
Yes, because a bool can be implicitly converted to a long, but a long cannot be implicitly converted to a bool.
Apr 25 2013
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 00:35:33 UTC, Walter Bright wrote:
 Is bool more specialized than long
Yes, because a bool can be implicitly converted to a long, but a long cannot be implicitly converted to a bool.
As we have bool literals as true and false, I don't think 1 should match bool in the first place.
Apr 25 2013
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, April 25, 2013 17:35:34 Walter Bright wrote:
 Is bool more specialized than long
Yes, because a bool can be implicitly converted to a long, but a long cannot be implicitly converted to a bool.
However, given that bool isn't even an integral type, it seems very wrong that it would be a better match than something which _is_ an integral type. Given that the compiler already inserts explicit casts to bool in conditions to solve the primary case where you want a non-boolean value to implicitly convert to bool, it really seems to me that the other conversions to and from bool which are currently accepted are far too lax. Another example of this would be something like "foo" ~ true. I don't understand why conversions like that are allowed by the spec. They're just going to cause bugs. - Jonathan M Davis
Apr 25 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 02:29:07 UTC, Jonathan M Davis wrote:
 On Thursday, April 25, 2013 17:35:34 Walter Bright wrote:
 Is bool more specialized than long
Yes, because a bool can be implicitly converted to a long, but a long cannot be implicitly converted to a bool.
However, given that bool isn't even an integral type, it seems very wrong that it would be a better match than something which _is_ an integral type. Given that the compiler already inserts explicit casts to bool in conditions to solve the primary case where you want a non-boolean value to implicitly convert to bool, it really seems to me that the other conversions to and from bool which are currently accepted are far too lax. Another example of this would be something like "foo" ~ true. I don't understand why conversions like that are allowed by the spec. They're just going to cause bugs. - Jonathan M Davis
And indeed they do. I did face some very weird bugs caused by that already.
Apr 25 2013
parent reply "ixid" <nuaccount gmail.com> writes:
 And indeed they do. I did face some very weird bugs caused by 
 that already.
What sort of bugs has it caused for you? Just interested, not questioning whether or not it's a source of bugs.
Apr 26 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 12:34:55 UTC, ixid wrote:
 And indeed they do. I did face some very weird bugs caused by 
 that already.
What sort of bugs has it caused for you? Just interested, not questioning whether or not it's a source of bugs.
The last time I experienced that feature was with a char getting casted to bool implicitly and then appended to a string, causing super weird behavior after when using the resulting (corrupted) string. I don't have the actual code as I threw it away (because it was bogous) but took me several hours to figure it out.
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 6:51 AM, deadalnix wrote:
 The last time I experienced that feature was with a char getting casted to bool
 implicitly and then appended to a string, causing super weird behavior after
 when using the resulting (corrupted) string.
void main() { bool b = 'c'; } dmd -c foo foo.d(4): Error: cannot implicitly convert expression ('c') of type char to bool
Apr 26 2013
parent "khurshid" <khurshid.normuradov gmail.com> writes:
On Friday, 26 April 2013 at 18:22:10 UTC, Walter Bright wrote:
 On 4/26/2013 6:51 AM, deadalnix wrote:
 The last time I experienced that feature was with a char 
 getting casted to bool
 implicitly and then appended to a string, causing super weird 
 behavior after
 when using the resulting (corrupted) string.
void main() { bool b = 'c'; } dmd -c foo foo.d(4): Error: cannot implicitly convert expression ('c') of type char to bool
import std.stdio; void main() { bool c0 = '\1'; //compiled OK bool c1 = '\0'; //compiled OK writeln(c0,' ',c1); //output: true false }
Apr 27 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Is is acceptable for 1 to match bool and 2 long? Maybe it is not 
acceptable in a serious language with strong typing...

Bye,
bearophile
Apr 25 2013
prev sibling next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Thursday, 25 April 2013 at 21:05:43 UTC, Ali Çehreli wrote:
 This question has first appeared on D.learn:

 ...

 The program calls two separate foo() overloads for 1 and 2:

 bool
 long

 According to the language spec, both overloads match the int 
 argument by "implicit conversion" as described under "Function 
 Overloading" here:

   http://dlang.org/function.html

 Then, the overload must be resolved by partial ordering: "If 
 two or more functions have the same match level, then partial 
 ordering is used to try to find the best match. Partial 
 ordering finds the most specialized function."

 Is bool more specialized than long or is this a bug? 
 Intuitively, both should match the 'long' overload. It feels 
 like there should at least be ambiguity.

 Ali
Looks like value range propagation bug because 1 is integer literal and should be converted to long. There is no way for 1 to be converted to bool here (from TDPL long is below int and it is the shortest way, value range propagation can work upwards, but the path would be longer).
Apr 25 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/25/2013 06:44 PM, Maxim Fomin wrote:

 On Thursday, 25 April 2013 at 21:05:43 UTC, Ali Çehreli wrote:
 Looks like value range propagation bug because 1 is integer literal and
 should be converted to long. There is no way for 1 to be converted to
 bool here
That special conversion rule of literal 0 and literal 1 being implicitly convertible to false and true gets in the way.
 (from TDPL long is below int and it is the shortest way, value
 range propagation can work upwards, but the path would be longer).
Interesting. I agree with bearophile, this is too surprising: foo(1); // goes to bool Decide to change the value: foo(2); // now goes to long Introduce a variable: int i = 1; foo(i); // again, goes to long I feel defeated. :) Ali
Apr 25 2013
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/26/13, Ali =C7ehreli <acehreli yahoo.com> wrote:
 Introduce a variable:

    int i =3D 1;
    foo(i);  // again, goes to long
An even better example: enum e =3D 1; void main() { foo(e); // bool } static e =3D 1; void main() { foo(e); // long } I find this unacceptable.
Apr 25 2013
prev sibling next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Friday, 26 April 2013 at 02:13:03 UTC, Ali Çehreli wrote:
 On 04/25/2013 06:44 PM, Maxim Fomin wrote:

 On Thursday, 25 April 2013 at 21:05:43 UTC, Ali Çehreli wrote:
 Looks like value range propagation bug because 1 is integer
literal and
 should be converted to long. There is no way for 1 to be
converted to
 bool here
That special conversion rule of literal 0 and literal 1 being implicitly convertible to false and true gets in the way.
 (from TDPL long is below int and it is the shortest way, value
 range propagation can work upwards, but the path would be
longer). Ali
Sorry but I am not aware of how 1 is converted to bool here. True, that 1 is convertible to true, but here there is function with long parameter.
Apr 26 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/26/2013 12:03 AM, Maxim Fomin wrote:
 On Friday, 26 April 2013 at 02:13:03 UTC, Ali Çehreli wrote:
 On 04/25/2013 06:44 PM, Maxim Fomin wrote:

 On Thursday, 25 April 2013 at 21:05:43 UTC, Ali Çehreli wrote:
 Looks like value range propagation bug because 1 is integer
literal and
 should be converted to long. There is no way for 1 to be
converted to
 bool here
That special conversion rule of literal 0 and literal 1 being implicitly convertible to false and true gets in the way.
 (from TDPL long is below int and it is the shortest way, value
 range propagation can work upwards, but the path would be
longer). Ali
Sorry but I am not aware of how 1 is converted to bool here. True, that 1 is convertible to true,
Yes, through an implicit conversion.
 but here there is function
 with long parameter.
Since the type of literal 1 is int, calling foo(long) would require an implicit conversion as well: from int to long. In the end, both functions are candidates because they both accept 1 by one implicit conversion. Ali
Apr 26 2013
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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" }
Apr 26 2013
next sibling parent "Rob T" <alanb ucora.com> writes:
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
Apr 26 2013
prev sibling next sibling parent reply "Mehrdad" <wfunction hotmail.com> writes:
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" }
Walter, you're completely missing the point. The point is that people can live with the consequences of your short/long example, but they can't do the same with Andrej's bool/long example. No matter how right you are, if you keep insisting your way is correct, D will continue never becoming popular because people will continue finding it hard to use. I think at some point it's worth noticing that "ease of use" is _not_ a linear function of "technical correctness". You may be right in technicality but that doesn't mean you're right on the UI side.
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 7:36 PM, Mehrdad wrote:
 Walter, you're completely missing the point.
I completely understand it is a perception problem. Some people see bool as a 1 bit integer (including me). Some see bool as something very distinct from integers (including you). An analogous issue comes up here now and then about 'char' and characters. Are chars an 8 byte integer, or are they characters, or are they octets, or should access only be allowed to multibyte characters as an indivisible code point? (This comes up in regards to indexing char[].)
 The point is that people can live with the consequences of your short/long
 example, but they can't do the same with Andrej's bool/long example.
 No matter how right you are, if you keep insisting your way is correct, D will
 continue never becoming popular because people will continue finding it hard to
 use.
What I find distressing about these kinds of threads is how people dig in and so fortify their position on a rather trivial matter and then it blows up into some do-or-die thing.
Apr 27 2013
next sibling parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Saturday, 27 April 2013 at 19:51:48 UTC, Walter Bright wrote:
 On 4/26/2013 7:36 PM, Mehrdad wrote:
 Walter, you're completely missing the point.
I completely understand it is a perception problem. Some people see bool as a 1 bit integer (including me). Some see bool as something very distinct from integers (including you).
The problem is 'bool' has *NOTHING* in common with integers! - Can't use + - * / << >> on bool's - (bool)2 == (bool)1 (do you SERIOUSLY think this is integer-like?) - sizeof(int64) == 8 * sizeof(int8) - sizeof(int8 ) != 8 * sizeof(bool) There is literally _NOTHING_ about bool that's integer-like, and for some reason you still think bool is an integer. And you still wonder why people find D frustrating?
 An analogous issue comes up here now and then about 'char' and 
 characters.
That was a C++ mistake, I hope you're not trying to repeat it. Heck, even in C++, you can make sense out of it if you stick with the convention: - "char" == character - "unsigned char" == ubyte - "signed char" == sbyte
Apr 27 2013
parent reply "Rob T" <alanb ucora.com> writes:
On Saturday, 27 April 2013 at 20:31:15 UTC, Mehrdad wrote:
 The problem is 'bool' has *NOTHING* in common with integers!

 - Can't use + - * / << >> on bool's
Because currently D views booleans as a 1 bit int, you can do seemingly nonsensical things with the bool type bool b = false + true; // OK bool b = true * true; // OK bool b = true / true; // OK bool b = true + true; // compile error because 2 does not fit into 1 bit. Even if you accept the view that bool is a 1 bit int, this conditional makes no sense at all int x = -123456; if (x) then { // evaluates to true, but why??? } if (x == true) then { // false because x != true(1), even though previously it was true } If bools are 1 bit ints, then why do we have 'true' and 'false' as keywords? Those keywords only serve to confuse the programmer into thinking that the bool type is actually a real boolean type. The worse thing about this situation is the inconsistencies. It would not be nearly as bad if bool really was a 1 bit int type, instead it sometimes behaves like an int and sometimes it behaves like a boolean. Why name name the type "bool" instead of "bit"? Why have true and false keywords? What I gather from the state of affairs, is an attempt to create the illusion of a boolean while retaining all of the properties of a 1 bit int type, with the notable exception of the weird conditional that evaluates an integer to true if it is not 0. --rt
Apr 27 2013
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
Apr 27 2013
next sibling parent reply "jerro" <a a.com> writes:
On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 
 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
I would expect boolean literals to be something like 0b and 1b, not true and false then.
Apr 27 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/27/2013 2:58 PM, jerro wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
I would expect boolean literals to be something like 0b and 1b, not true and false then.
To reiterate, history amply shows that if 'true' and 'false' are not there, then people will define them themselves, inconsistently, and the end result is not helpful to anybody.
Apr 28 2013
next sibling parent reply "eles" <eles eles.com> writes:
On Sunday, 28 April 2013 at 19:19:53 UTC, Walter Bright wrote:
 On 4/27/2013 2:58 PM, jerro wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright
To reiterate, history amply shows that if 'true' and 'false' are not there, then people will define them themselves, inconsistently, and the end result is not helpful to anybody.
So basically, those are to be seen as simple #defines for 0 and 1 and nothing more than that? I am for a boolean type that is only true and false. And, if so much needed conversion from int 0 and int non0 to boolean is needed in if() and while(), then simply add ifz(), ifnz(), whilez() and whilenz() to the language. (that is: ifzero(), infnonzero(), whilezero(), whilenonzero()). This will really convey the intention of the programmer. Elsewhere, I see no reason to accept implicit cast from bool to int, and less so in function overloading. I am in favor of a true boolean type, nothing to do with integers, and of helpers where needed. Besides, I do not like the idea of a bit type, because of its fractional representation (you need to use an entire byte for it, and unlike other (integer) types, its maximum range of values *does not* completely cover the width of its representation). I would rather accept a ranged-type that goes from 0 to 1 (sub-range of integers). In Pascal that would be: 0..1, with a zero-based index
Apr 28 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 28 April 2013 at 19:38:26 UTC, eles wrote:
 On Sunday, 28 April 2013 at 19:19:53 UTC, Walter Bright wrote:
 On 4/27/2013 2:58 PM, jerro wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright
To reiterate, history amply shows that if 'true' and 'false' are not there, then people will define them themselves, inconsistently, and the end result is not helpful to anybody.
So basically, those are to be seen as simple #defines for 0 and 1 and nothing more than that? I am for a boolean type that is only true and false. And, if so much needed conversion from int 0 and int non0 to boolean is needed in if() and while(), then simply add ifz(), ifnz(), whilez() and whilenz() to the language. (that is: ifzero(), infnonzero(), whilezero(), whilenonzero()).
This is plain useless as a cast is already inserted here.
Apr 29 2013
next sibling parent "eles" <eles eles.com> writes:
On Monday, 29 April 2013 at 12:30:06 UTC, deadalnix wrote:
 On Sunday, 28 April 2013 at 19:38:26 UTC, eles wrote:
 On Sunday, 28 April 2013 at 19:19:53 UTC, Walter Bright wrote:
 On 4/27/2013 2:58 PM, jerro wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright
This is plain useless as a cast is already inserted here.
so, only allow explict casting then.
Apr 29 2013
prev sibling parent reply Sean Cavanaugh <WorksOnMyMachine gmail.com> writes:
On 4/29/2013 7:30 AM, deadalnix wrote:
 (that is: ifzero(), infnonzero(), whilezero(), whilenonzero()).
int x = 3; if (!!x) { // do something } Its not official but this already works in the C like langauges, as a way to 'promote to bool'
Apr 29 2013
parent "eles" <eles eles.com> writes:
On Monday, 29 April 2013 at 18:53:22 UTC, Sean Cavanaugh wrote:
 On 4/29/2013 7:30 AM, deadalnix wrote:
 Its not official but this already works in the C like 
 langauges, as a way to 'promote to bool'
I know, but I still think that ifz() and ifnz() convey better (more, they are easier to debug, but that's subjective). However, is not a big deal.
Apr 29 2013
prev sibling parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Sunday, 28 April 2013 at 19:19:53 UTC, Walter Bright wrote:
 On 4/27/2013 2:58 PM, jerro wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright 
 wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 
 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
I would expect boolean literals to be something like 0b and 1b, not true and false then.
To reiterate, history amply shows that if 'true' and 'false' are not there, then people will define them themselves, inconsistently, and the end result is not helpful to anybody.
History also amply shows that having a 'bool' data type that tries to behave like a 'bit' data type also leads to frustration. See: - This thread - std::vector<bool>
Apr 28 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2013 10:54 PM, Mehrdad wrote:
 On Sunday, 28 April 2013 at 19:19:53 UTC, Walter Bright wrote:
 ...

 To reiterate, history amply shows that if 'true' and 'false' are not
 there, then people will define them themselves, inconsistently, and
 the end result is not helpful to anybody.
History also amply shows that having a 'bool' data type that tries to behave like a 'bit' data type also leads to frustration. See: - This thread
"History".
 - std::vector<bool>
The issues surrounding vector<bool> are entirely unrelated.
Apr 28 2013
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Sunday, 28 April 2013 at 21:29:06 UTC, Timon Gehr wrote:
 On 04/28/2013 10:54 PM, Mehrdad wrote:
 - std::vector<bool>
The issues surrounding vector<bool> are entirely unrelated.
Huh? It's entirely related. The fact that sizeof(bool) * 8 != sizeof(byte) is what causes problems in vector<bool> (can't treat them like other types, which we can address directly), and it's also one of the asymmetries bool has with integers in D (and any other language). Different situation, same cause: bool doesn't behave like an integer.
 Isn't that self-contradictory?
 He is saying bool is an integral type in D. (i.e. it can be 
 promoted to
'int' in order to support integer arithmetic.) I thought we just established that boolean logic isn't integer logic?
Apr 28 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2013 11:51 PM, Mehrdad wrote:
 On Sunday, 28 April 2013 at 21:29:06 UTC, Timon Gehr wrote:
 On 04/28/2013 10:54 PM, Mehrdad wrote:
 - std::vector<bool>
The issues surrounding vector<bool> are entirely unrelated.
Huh? It's entirely related. The fact that sizeof(bool) * 8 != sizeof(byte) is what causes problems in vector<bool>
Exactly. This is not the problem here.
 (can't treat them like other types, which we can address
 directly), and it's also one of the asymmetries bool has with integers
 in D (and any other language).

 Different situation, same cause: bool doesn't behave like an integer.
The issue discussed here is that some think it behaves too much like an integer.
 Isn't that self-contradictory?
 He is saying bool is an integral type in D. (i.e. it can be promoted to
'int' in order to support integer arithmetic.) I thought we just established that boolean logic isn't integer logic?
Please make sure your statements make sense.
Apr 28 2013
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Sunday, 28 April 2013 at 22:25:43 UTC, Timon Gehr wrote:
 On 04/28/2013 11:51 PM, Mehrdad wrote:
 On Sunday, 28 April 2013 at 21:29:06 UTC, Timon Gehr wrote:
 On 04/28/2013 10:54 PM, Mehrdad wrote:
 Isn't that self-contradictory?
 He is saying bool is an integral type in D. (i.e. it can be 
 promoted to 'int' in order to support integer arithmetic.)
I thought we just established that boolean logic isn't integer logic?
Please make sure your statements make sense.
Huh? Walter says bool is an integer, but he understands that boolean variables don't follow integer logic. That makes no sense, it's like saying "I understand the sky is blue, but the sky is red." What part of this is not making sense to you?
Apr 28 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2013 12:51 AM, Mehrdad wrote:
 On Sunday, 28 April 2013 at 22:25:43 UTC, Timon Gehr wrote:
 On 04/28/2013 11:51 PM, Mehrdad wrote:
 On Sunday, 28 April 2013 at 21:29:06 UTC, Timon Gehr wrote:
 On 04/28/2013 10:54 PM, Mehrdad wrote:
 Isn't that self-contradictory?
 He is saying bool is an integral type in D. (i.e. it can be promoted
 to 'int' in order to support integer arithmetic.)
I thought we just established that boolean logic isn't integer logic?
Please make sure your statements make sense.
Huh? Walter says bool is an integer,
Certainly not. bool is a type. 2 is an integer. He says that bool is an integral type (which has a very specific meaning, lined out above.)
 but he understands that boolean variables don't follow integer logic.

 That makes no sense, it's like saying "I understand the sky is blue, but
 the sky is red."
Check his statements again, I guess.
 What part of this is not making sense to you?
Eg. "integer logic".
Apr 28 2013
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Sunday, 28 April 2013 at 23:11:50 UTC, Timon Gehr wrote:
 On 04/29/2013 12:51 AM, Mehrdad wrote:
 On Sunday, 28 April 2013 at 22:25:43 UTC, Timon Gehr wrote:
 On 04/28/2013 11:51 PM, Mehrdad wrote:
 On Sunday, 28 April 2013 at 21:29:06 UTC, Timon Gehr wrote:
 On 04/28/2013 10:54 PM, Mehrdad wrote:
 Isn't that self-contradictory?
 He is saying bool is an integral type in D. (i.e. it can be 
 promoted
 to 'int' in order to support integer arithmetic.)
I thought we just established that boolean logic isn't integer logic?
Please make sure your statements make sense.
Huh? Walter says bool is an integer,
Certainly not. bool is a type. 2 is an integer.
Sheesh, s/bool/a bool/.
 He says that bool is an integral type (which has a very 
 specific meaning, lined out above.)
o__O why would he waste time commenting on how D _behaves_? Isn't the whole point of the discussion to figure out how D _should_ behave? It's not like we haven't understood what the compiler is doing!
 Eg. "integer logic".
Integer logic: 1 + 1 = 2 = 0 (mod 2) Boolean logic: 1 + 1 = 1 = 1
Apr 28 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/28/13 7:19 PM, Mehrdad wrote:
 Integer logic: 1 + 1 = 2 = 0 (mod 2)
 Boolean logic: 1 + 1 = 1 = 1
Well D doesn't implement Boolean operators for + and *. Instead, one would need to use | and & respectively. When + and * are used with bool, promotion to int happens. I think it's safe to assume D will never implement the Boolean meaning of + and *. Andrei
Apr 28 2013
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Sunday, 28 April 2013 at 23:37:23 UTC, Andrei Alexandrescu 
wrote:
 On 4/28/13 7:19 PM, Mehrdad wrote:
 Integer logic: 1 + 1 = 2 = 0 (mod 2)
 Boolean logic: 1 + 1 = 1 = 1
Well D doesn't implement Boolean operators for + and *. Instead, one would need to use | and & respectively.When + and * are used with bool, promotion to int happens. I think it's safe to assume D will never implement the Boolean meaning of + and *.
Sure. But when bool behaves only halfway like an integer (why doesn't it truncate when casting?) and it _also_ will never implement Boolean algebra with + and * (which is fine by me, I never requested that it does) then it should fix _one_ of those two aspects of itself in order to be self-consistent. We threw out the Boolean algebra fix, so the only choice is to either make it behave entirely like an integer, or to make it be a completely different type. In other words, we need to either: 1. Make int->bool truncate, or 2. Stop allowing implicit bool->int conversions (explicit conversions like in if/while/etc. are of course not included here)
Apr 28 2013
next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Sunday, 28 April 2013 at 23:47:20 UTC, Mehrdad wrote:
 2. Stop allowing implicit bool->int conversions
And implicit int->bool as well, forgot to mention that.
Apr 28 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/28/13 7:47 PM, Mehrdad wrote:
 In other words, we need to either:

 1. Make int->bool truncate, or
Not going to happen.
 2. Stop allowing implicit bool->int conversions (explicit conversions
 like in if/while/etc. are of course not included here)
Unlikely to ever happen.
 And implicit int->bool as well, forgot to mention that.
That may have a chance. Andrie
Apr 28 2013
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Monday, 29 April 2013 at 00:40:08 UTC, Andrei Alexandrescu 
wrote:
 2. Stop allowing implicit bool->int conversions (explicit 
 conversions like in if/while/etc. are of course not included 
 here)
Unlikely to ever happen.
What's the use case against it?
Apr 28 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 29 April 2013 at 00:45:47 UTC, Mehrdad wrote:
 On Monday, 29 April 2013 at 00:40:08 UTC, Andrei Alexandrescu 
 wrote:
 2. Stop allowing implicit bool->int conversions (explicit 
 conversions like in if/while/etc. are of course not included 
 here)
Unlikely to ever happen.
What's the use case against it?
This is useful, and do not cause problem by itself. The reverse conversion is problematic.
Apr 29 2013
prev sibling next sibling parent reply "eles" <eles eles.com> writes:
On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 Because writing cast(bool)0 and cast(bool)1 is unappealing.
why need to write that? just drop the bool type entirely and go ahead with an integer that you interpret as a boolean. welcome back to C (k&r).
Apr 27 2013
parent "Rob T" <alanb ucora.com> writes:
On Saturday, 27 April 2013 at 21:59:50 UTC, eles wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 Because writing cast(bool)0 and cast(bool)1 is unappealing.
why need to write that? just drop the bool type entirely and go ahead with an integer that you interpret as a boolean.
The problem is that Walter appears to want the convenience of a real bool type, but also the convenience of a real bit type, all merged together into one container that is confusingly labeled as 'bool'. See my previous post about the problems caused when merging two conceptually different things into one container and then make it appear as if it stores only one of the conceptually different things - sometimes. Thats never a good idea. We can solve the problem by defining a real boolean type and a real bit type and allow explicit casting if required (which should be rare). --rt
Apr 27 2013
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 
 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
Unappealing to whom?
Apr 27 2013
prev sibling next sibling parent Paulo Pinto <pjmlp progtools.org> writes:
Am 27.04.2013 23:52, schrieb Walter Bright:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 'false' as
 keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
No, this brings us back into the realm of C and weak type checking.
Apr 27 2013
prev sibling next sibling parent "Rob T" <alanb ucora.com> writes:
On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 
 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
That cannot be the main reason. There must be a more fundamental reason for having true and false (which is inconsistent with ints) instead of 1b and 0b (which is consistent with ints). --rt
Apr 27 2013
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 27, 2013 14:52:31 Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 'false' as
 keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
You'd only be forced to do that outside of conditions, as the cast is already inserted for you in conditions. And if you really need bool, one could argue that it doesn't make sense to be using integer literals anyway. We already have true and false if you really want a bool when deal with literals. I like being able to do while(1) because it's shorter, but it's not ultimately all that onerous to have to do while(true), and the casting in conditions takes care of that case anyway. In most cases, simply using a bool when you mean bool, and an int when you want an integral type solves the problem quite cleanly. The main place that I can see that it makes sense to end up with casts to and from bool which might get annoying is if you're trying to use bools in arithmetic, and I honestly don't think that allowing implicit casts there is worth all of the other weirdness it causes in the language in general. - Jonathan M Davis
Apr 27 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2013 02:28 AM, Jonathan M Davis wrote:
 ...  I like
 being able to do while(1) because it's shorter, ...
for(;;) is shorter.
Apr 27 2013
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 28, 2013 02:53:04 Timon Gehr wrote:
 On 04/28/2013 02:28 AM, Jonathan M Davis wrote:
 ...  I like
 being able to do while(1) because it's shorter, ...
for(;;) is shorter.
True, but I'd never use it, because I'd never use a for loop for anything that didn't involve either creating a variable in the first portion of the for or doing something in the last portion. I also find it very bizarre that it's legal to have a loop _without_ a condition like for(;;) does. If you couldn't do while(1), I'd do while(true) and never for(;;), but that's obviously a matter of preference, and while I like being able to do while(1), I'd gladly give it up if that meant that we stopped treating bool as in integral type. - Jonathan M Davis
Apr 27 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 
 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
VRP say you don't need to.
Apr 28 2013
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 28 April 2013 at 09:05:06 UTC, deadalnix wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 
 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
VRP say you don't need to.
Which is kind o funny, because we didn't had to wait for long before you felt in the trap as well. Hard to maintain it isn't confusing now . . .
Apr 28 2013
prev sibling next sibling parent "Rob T" <alanb ucora.com> writes:
On Sunday, 28 April 2013 at 09:05:06 UTC, deadalnix wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 
 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
VRP say you don't need to.
I was wondering who was going to notice that elephant. I didn't get a satisfactory answer to the question of why we have an int type named bool with special keywords true and false, when if it really is an int type, all we require is a type named bit with nothing else needed other than what is already available with int types. bool is a very unusual beast, but why? --rt
Apr 28 2013
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2013 11:05 AM, deadalnix wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 'false' as
 keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
VRP say you don't need to.
void foo(bool b){ } // 1 void foo(int i){ } // 2 void main(){ foo(cast(bool)0); // calls 1 foo(0); // calls 2 }
Apr 28 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2013 2:05 AM, deadalnix wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
VRP say you don't need to.
You're implying there is no need for 1L or 1U either, but there is. The other reason, mentioned before, is that without making them a keyword or standard type, people will inevitably create their own in one of many different, incompatible, ways.
Apr 28 2013
parent reply "Diggory" <diggsey googlemail.com> writes:
On Monday, 29 April 2013 at 06:26:44 UTC, Walter Bright wrote:
 On 4/28/2013 2:05 AM, deadalnix wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright 
 wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
 If bools are 1 bit ints, then why do we have 'true' and 
 'false' as keywords?
Because writing cast(bool)0 and cast(bool)1 is unappealing.
VRP say you don't need to.
You're implying there is no need for 1L or 1U either, but there is. The other reason, mentioned before, is that without making them a keyword or standard type, people will inevitably create their own in one of many different, incompatible, ways.
The same could be said of booleans. If D does not have a proper logical boolean type rather than a "bit" then people will simply write their own (conflicting and likely inefficient) boolean types which work the way they expect. I've actually used a language where boolean is effectively a 1-bit integer, and I can safely say that I have never found a single advantage over a language with more strongly type booleans which can implicitly be cast to int, but not the other way around. On the other hand the disadvantages are quite extensive: confusion for anyone who has ever used any other high level language, confusing overload resolution as shown in this thread, special cases (booleans convert by comparison rather than truncation, obviously truncation would be stupid but I think this is more of a reason to ditch integer booleans rather than to introduce a special case), different meaning (an integer is a number, a boolean is more like a yes/no enum and that is how it will be used in almost all code regardless of how it is defined in the language), etc.
Apr 29 2013
parent reply "eles" <eles eles.com> writes:
On Monday, 29 April 2013 at 09:49:59 UTC, Diggory wrote:
 On Monday, 29 April 2013 at 06:26:44 UTC, Walter Bright wrote:
 On 4/28/2013 2:05 AM, deadalnix wrote:
 On Saturday, 27 April 2013 at 21:52:30 UTC, Walter Bright 
 wrote:
 On 4/27/2013 2:29 PM, Rob T wrote:
this thread, special cases (booleans convert by comparison rather than truncation, obviously truncation would be stupid but I think this is more of a reason to ditch integer booleans rather than to introduce a special case), different meaning (an integer is a number, a boolean is more like a yes/no enum and that is how it will be used in almost all code regardless of how it is defined in the language), etc.
gdc: bool x = false; x++; main.d:50: Error: operation not allowed on bool 'x' why not? is just an integer after all. another special case? this works: int x = false; x++;
Apr 29 2013
parent reply "Mike James" <foo bar.com> writes:
 gdc:

 bool x = false;
 x++;

 main.d:50: Error: operation not allowed on bool 'x'

 why not? is just an integer after all. another special case?
If you are going to create a boolean then use it as a boolean - it's not an integer any more. Don't mix and match - there's nothing worse than trying to follow some code that uses a variable in one way then, out of lazyness, uses it in a different way.
 this works:

 int x = false;
 x++; 
Apr 29 2013
next sibling parent "eles" <eles eles.com> writes:
On Monday, 29 April 2013 at 14:08:20 UTC, Mike James wrote:
 gdc:

 bool x = false;
 x++;

 main.d:50: Error: operation not allowed on bool 'x'

 why not? is just an integer after all. another special case?
If you are going to create a boolean then use it as a boolean - it's not an integer any more. Don't mix and match - there's nothing worse than trying to follow some code that uses a variable in one way then, out of lazyness, uses it in a different way.
that was exactly my point. that a boolean *should not* be an integer. and the case that I presented shows just another inconsistency of the relationship between booleans and integers in D. it works one way when it comes to function overloading, and another way when it comes to, let's say, ++ operator.
Apr 29 2013
prev sibling parent "Rob T" <alanb ucora.com> writes:
On Monday, 29 April 2013 at 14:08:20 UTC, Mike James wrote:
 gdc:

 bool x = false;
 x++;

 main.d:50: Error: operation not allowed on bool 'x'

 why not? is just an integer after all. another special case?
If you are going to create a boolean then use it as a boolean - it's not an integer any more. Don't mix and match - there's nothing worse than trying to follow some code that uses a variable in one way then, out of lazyness, uses it in a different way.
 this works:

 int x = false;
 x++;
The main point made in this thread is that because bool is not really an integral type, you cannot use it as one, but D overloads integral types with bool which is clearly wrong. You also cannot in general interchange ints and bools inside a template without special conditions to differentiate between them the two (eg ++bool fails), therefore bool should not overload on ints or implicitly cast to/from ints and bools under most situations. --rt
Apr 29 2013
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 If bools are 1 bit ints, then why do we have 'true' and 'false' 
 as keywords? Those keywords only serve to confuse the 
 programmer into thinking that the bool type is actually a real 
 boolean type.
C++ has also true and false and they are converted to integers by the compiler.
Apr 27 2013
prev sibling next sibling parent "Rob T" <alanb ucora.com> writes:
On Saturday, 27 April 2013 at 19:51:48 UTC, Walter Bright wrote:
 An analogous issue comes up here now and then about 'char' and 
 characters. Are chars an 8 byte integer, or are they 
 characters, or are they octets, or should access only be 
 allowed to multibyte characters as an indivisible code point? 
 (This comes up in regards to indexing char[].)
The real problem I think is caused by trying to fit two conceptually different things into the same container and then merging the two conceptually different behaviors together. It's very confusing and causes unexpected conflicts. My analogy is having two exactly identical containers labeled "water", but use one to store water and the other gasoline, then wait until someone yells "fire!". To solve the char problem, what should be done, is have a real 'char' type and a real 'byte' type to settle the matter, and use explicit casting where required. To transform bool into something sensible that we can all agree with, there should a a 'bool' type and a 'bit' type, and use explicit casting where required. What we have instead is a confounding merging of dissimilar containers for conflicting purposes. This is completely avoidable and easily so. --rt
Apr 27 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 27 April 2013 at 19:51:48 UTC, Walter Bright wrote:
 On 4/26/2013 7:36 PM, Mehrdad wrote:
 Walter, you're completely missing the point.
I completely understand it is a perception problem. Some people see bool as a 1 bit integer (including me). Some see bool as something very distinct from integers (including you).
Don't be silly. You don't see them as 1 bit integer, as they convert by comparing to 0 and not truncating.
 What I find distressing about these kinds of threads is how 
 people dig in and so fortify their position on a rather trivial 
 matter and then it blows up into some do-or-die thing.
It is not like this issue is popping for the first time. When a source of tension exists, any complaint about it can crystallize easily.
Apr 27 2013
parent =?UTF-8?B?Ikx1w61z?= Marques" <luismarques gmail.com> writes:
On Sunday, 28 April 2013 at 01:54:50 UTC, deadalnix wrote:
 Don't be silly. You don't see them as 1 bit integer, as they 
 convert by comparing to 0 and not truncating.
This corroborates Rob T's positions that the current bool type tries to be both a bit and a logical Boolean and ends up not quite living to either, right? Also, while reading this thread I kept wondering: if some tweak of bool was decided, wouldn't it be great to have something like Go's gofmt for automatic conversion of existing code?
Apr 27 2013
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 27 Apr 2013 12:51:48 -0700, Walter Bright  
<newshound2 digitalmars.com> wrote:

 On 4/26/2013 7:36 PM, Mehrdad wrote:
 Walter, you're completely missing the point.
I completely understand it is a perception problem. Some people see bool as a 1 bit integer (including me). Some see bool as something very distinct from integers (including you).
short x = cast(short)0x10000; assert(x == 0); bool b = cast(bool)2; assert(b == 1); // NOT 2s complement bool is not an integer. It doesn't behave like any other integer type. Because it has some power to implicitly cast to int, this does not make it an integer. -Steve
Apr 29 2013
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, April 29, 2013 09:54:40 Steven Schveighoffer wrote:
 On Sat, 27 Apr 2013 12:51:48 -0700, Walter Bright
 
 <newshound2 digitalmars.com> wrote:
 On 4/26/2013 7:36 PM, Mehrdad wrote:
 Walter, you're completely missing the point.
I completely understand it is a perception problem. Some people see bool as a 1 bit integer (including me). Some see bool as something very distinct from integers (including you).
short x = cast(short)0x10000; assert(x == 0); bool b = cast(bool)2; assert(b == 1); // NOT 2s complement bool is not an integer. It doesn't behave like any other integer type. Because it has some power to implicitly cast to int, this does not make it an integer.
It also isn't considered to be an integral type per std.traits.isIntegral. isIntegral only considers byte, ubyte, short, ushort, int, uint, long, and ulong to be integral types. - Jonathan M Davis
Apr 29 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
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" }
VRP should be used as a fallback mechanism. Yes, kill it with fire.
Apr 27 2013
parent "Diggory" <diggsey googlemail.com> writes:
On Saturday, 27 April 2013 at 10:17:58 UTC, deadalnix wrote:
 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" }
VRP should be used as a fallback mechanism. Yes, kill it with fire.
I agree 100% VRP is nice but it should not be used implicitly to resolve ambiguous cases, that definitely goes against least surprise and all that.
Apr 27 2013
prev sibling next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
First, I can guess that why Walter disagree *fixing* this problem.

http://dlang.org/overview.html
 Major Design Goals of D
 9. Where D code looks the same as C code, have it either behave the same
or issue an error. Based on the design goal, we should not change the behavior toward foo(1) matching to long version. It will change the code behavior that looks like C. But, we can raise an "ambiguous error" for the case. I think we need to add a "special rule" for more natural overload resolution in D. // The expected behavior we can do at the most extern(C) int printf(const char*, ...); void foo(bool) { printf("bool\n"); } void foo(long) { printf("long\n"); } void main() { foo(0); // Error: function foo called with argument types: (int) matches both foo(bool) and foo(long) foo(1); // Error: function foo called with argument types: (int) matches both foo(bool) and foo(long) foo(2); // OK, matches to long } Kenji Hara 2013/4/27 Walter Bright <newshound2 digitalmars.com>
 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" }
Apr 27 2013
parent reply "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
On Saturday, 27 April 2013 at 11:41:30 UTC, kenji hara wrote:
 First, I can guess that why Walter disagree *fixing* this 
 problem.

 http://dlang.org/overview.html
 Major Design Goals of D
 9. Where D code looks the same as C code, have it either 
 behave the same
or issue an error.
C doesn't have a bool type, so how can D behave the same?
Apr 27 2013
next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
OK. I misunderstood.

C does not allow function overloading, so same problem is not there.
In C++,

// test.cpp
#include <stdio.h>
void foo(bool) { printf("bool\n"); }
void foo(long) { printf("long\n"); }
int main(int argc, char **argv)
{
foo(false);  // matches bool version
foo(true);   // matches bool version
foo(0);  // ambiguous
foo(1);  // ambiguous
foo(2);  // ambiguous
return 0;
}

The behavior is same with GCC 4.7.2 (using msys) and dmc.

Walter, now I changed my opinion. It seems not correct that being regarded
bool type as one of the integer.
How about?

Kenji Hara

2013/4/27 Minas Mina <minas_mina1990 hotmail.co.uk>

 On Saturday, 27 April 2013 at 11:41:30 UTC, kenji hara wrote:

 First, I can guess that why Walter disagree *fixing* this problem.

 http://dlang.org/overview.html

 Major Design Goals of D
 9. Where D code looks the same as C code, have it either behave the same
or issue an error.
C doesn't have a bool type, so how can D behave the same?
Apr 27 2013
next sibling parent "MattCoder" <mattcoder hotmail.com> writes:
One of the main problem that I saw here, is this behavior (DMD 
2.062):

import std.stdio;

void foo(bool b) { writeln("bool"); }
void foo(long l) { writeln("long"); }

void main()
{
int num = 0;

foo(num);
foo(0);
foo(2);
}

output:
long
bool
long

As num = 0, for me both: "foo(num)" and "foo(0)" should give the 
same output ("long"), regardless that num is integer implicit 
declaration or not.
Apr 27 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/27/2013 8:11 AM, kenji hara wrote:
 Walter, now I changed my opinion. It seems not correct that being regarded bool
 type as one of the integer.
 How about?
Both C and C++ regard bool as an integer, and implicitly convert 1/0 to true/false. What C++ doesn't have is VRP and partial ordering of functions. (But it does have partial ordering of template functions.)
Apr 27 2013
next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
2013/4/28 Walter Bright <newshound2 digitalmars.com>

 On 4/27/2013 8:11 AM, kenji hara wrote:

 Walter, now I changed my opinion. It seems not correct that being
 regarded bool
 type as one of the integer.
 How about?
Both C and C++ regard bool as an integer, and implicitly convert 1/0 to true/false. What C++ doesn't have is VRP and partial ordering of functions. (But it does have partial ordering of template functions.)
I'm not argue that we should remove the implicit conversion from 1/0 to bool. I don't have so much knowledge about C/C++ language spec, but for the issue case C++ makes "ambiguous error". Contrary of that, D's current behavior looks to me it is going back to past. Kenji Hara
Apr 27 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/27/2013 1:26 PM, kenji hara wrote:
 I don't have so much knowledge about C/C++ language spec, but for the issue
case
 C++ makes "ambiguous error".
That's because C++ regards an implicit conversion of 1 to bool or long as having equal weight, and it has no further mechanism.
Apr 27 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/27/2013 3:58 PM, Walter Bright wrote:
 On 4/27/2013 1:26 PM, kenji hara wrote:
 I don't have so much knowledge about C/C++ language spec, but for the issue
case
 C++ makes "ambiguous error".
That's because C++ regards an implicit conversion of 1 to bool or long as having equal weight, and it has no further mechanism.
Note that the following is also ambiguous in C++: void foo(bool b) { } void foo(long l) { } void main() { foo(3); }
Apr 27 2013
next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
2013/4/28 Walter Bright <newshound2 digitalmars.com>

 On 4/27/2013 3:58 PM, Walter Bright wrote:

 On 4/27/2013 1:26 PM, kenji hara wrote:

 I don't have so much knowledge about C/C++ language spec, but for the
 issue case
 C++ makes "ambiguous error".
That's because C++ regards an implicit conversion of 1 to bool or long as having equal weight, and it has no further mechanism.
Note that the following is also ambiguous in C++: void foo(bool b) { } void foo(long l) { } void main() { foo(3); }
Yes, but all C++ users would accept the behavior - In C++, all integer types are treated as bool type under the rule that zero/non-zero value is equivalent to false /true. From the view of D user, it looks inconvenient, but there is still few and consistent rule. On the other hand, D looks like having *special rule* of 0 and 1 literal for boolean type. Even if the underlying rule is sane (partial ordering rule and VRP), the combination makes weird behavior. ---- Now I doubt that this problem comes from the history of D and wrong dmd implementation. In early D1 age, we had had 'bit' type which exactly have one bit value 0 and 1. After the while, the name 'bit' changed to 'bool'. At that point, 'bool' was kept the characteristics that it is one of the integer types - even though we should discard it. Right? VRP is a new concept that introduced in D2 age. But, maybe, the combination of bool and VRP had not been considered enough. So now problem is appeared there. Now it feels to me that is a debt from D1. Kenji Hara
Apr 27 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/27/2013 9:38 PM, kenji hara wrote:
 On the other hand, D looks like having *special rule* of 0 and 1 literal for
 boolean type. Even if the underlying rule is sane (partial ordering rule and
 VRP), the combination makes weird behavior.
Again, whether it is "weird" or not comes from your perspective. From mine, a bool is a 1 bit integer. There is nothing weird about its behavior - it behaves just like all the other integer types.
Apr 28 2013
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 28 April 2013 at 08:40:01 UTC, Walter Bright wrote:
 On 4/27/2013 9:38 PM, kenji hara wrote:
 On the other hand, D looks like having *special rule* of 0 and 
 1 literal for
 boolean type. Even if the underlying rule is sane (partial 
 ordering rule and
 VRP), the combination makes weird behavior.
Again, whether it is "weird" or not comes from your perspective. From mine, a bool is a 1 bit integer. There is nothing weird about its behavior - it behaves just like all the other integer types.
Then be consistent. Convert int to bool by truncating.
Apr 28 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/28/13 4:40 AM, Walter Bright wrote:
 On 4/27/2013 9:38 PM, kenji hara wrote:
 On the other hand, D looks like having *special rule* of 0 and 1
 literal for
 boolean type. Even if the underlying rule is sane (partial ordering
 rule and
 VRP), the combination makes weird behavior.
Again, whether it is "weird" or not comes from your perspective. From mine, a bool is a 1 bit integer. There is nothing weird about its behavior - it behaves just like all the other integer types.
Let me start by saying that I agree with the view that this isn't a large or important issue; also, as language proponents with a lot of things to look at and work on, it seems inefficient to develop the language from one strident argument to another regardless of their true weight. That being said, I don't think Walter is framing the problem correctly. The advantage of his approach is simplicity: bool is to the extent possible a 1-bit integer (with particularities stemming from its small size). (I presume it's an unsigned type btw.) That makes a lot of rules that apply to integers also apply automatically to bool. There remain a few peculiarities that have been mentioned: 1. The relationship between sizeof(bool), the cardinality of Boolean values, .min and .max etc are unlike that for integers. 2. Conversion rules from other integrals to bool (0 is preserved, nonzero is converted to 1) are different than among non-bool integrals (truncation etc). 3. A variety of operators (such as += or *=) are not allowed for bool. These distinctions (probably there are a few subtler ones) and their consequences erode the simplicity advantage. Any serious argument based on simplicity should acknowledge that. The larger issue here goes back to good type system design. At the highest level, a type system aspires to: (a) allow sensible and interesting programs to be written easily; and (b) disallow non-sensible or uninteresting programs from being written. Real type systems inevitably allow at least a few uninteresting programs to be written, and fail to allow some interesting programs. The art is in minimizing the size of these sets. From that perspective, bool, as a first-class built-in type, fares rather poorly. It allows a variety of nonsensical programs to pass typechecking. For example, bool is allowed as the denominator in a division or reminder operation. There is no meaningful program that could use such an allowance: the computation is either trivial if the bool is true, or stuck if it's false. Then there is a gray area, such as multiplying an integer by a bool; arguably "a * b" is a shortcut for "if (!b) a = 0;" or "b ? a : 0" or "a * (b ? 1 : 0)" if b is a boolean. One might argue this is occasionally useful. Then there is a firmer area of cooperation between bool and other numerics, e.g. a[0 .. a.length - b], where b is a bool. I'm seeing these in code now and then and I occasionally write them. I personally find code that needs to use a[0 .. a.length - (b ? 1 : 0)] rather pedestrian, but not unbearably so. Tightening the behavior of bool to disallow nonsensical programs is arguably a good thing to do. Arguing against it would need to explain e.g. why operations such as "b1 *= b2" (with b1 and b2 of type bool) were deemed undesirable but "b1 / b2" was not. If enough differences accumulate to make bool quite a different type from a regular integral, then the matter of overloading with long, conversion from literals 1 and 0 etc. may be reopened. Even then, it would be a difficult decision. Finally, I felt compelled to add a larger point. This:
 It's like designing a house with a fixed footprint. You can make the
 kitchen larger and the bathroom smaller, or vice versa, but you can't
 make them both bigger.
This is a terrible mental pattern to put oneself in. Design problems often seem - or can be framed - as such, and the zero-sum-game pattern offers a cheap argument for denying further consideration. We've been stuck in many problems that looked that way, and the first step is to systematically destroy that pattern from the minds of everyone involved. We've been quite successful at that a few times: template constraints, integral conversions and VRP, cascaded comparisons "a < b < c", ordering comparisons between signed and unsigned integrals, and more. They all seemed to be zero-sum design problems to which no approach was better than others; once that was removed and ingenuity was allowed to say its word, solutions that had escaped scrutiny came on the table. From the perspective of the zero-sum game, those are nothing short of miraculous. Andrei
Apr 28 2013
next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 28 April 2013 at 13:38:53 UTC, Andrei Alexandrescu 
wrote:
 [Many things that make sense]
I think you missed a point I tried to raise several time unsuccessfully, and which is IMO very important. VRP should behave as a fallback mechanism. IE, VRP should kick in when the situation would result as an error without. Integrals literals must be typed as integral types, so never match bool when an overload with an integral is available (same goes for byte or short).
Apr 28 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2013 8:21 AM, deadalnix wrote:
 VRP should behave as a fallback mechanism. IE, VRP should kick in when the
 situation would result as an error without. Integrals literals must be typed as
 integral types, so never match bool when an overload with an integral is
 available (same goes for byte or short).
This is a restatement of the notion of a "better" match, which I've written about extensively in this thread.
Apr 28 2013
prev sibling parent "Rob T" <alanb ucora.com> writes:
On Sunday, 28 April 2013 at 13:38:53 UTC, Andrei Alexandrescu 
wrote:
[...]
 If enough differences accumulate to make bool quite a different 
 type from a regular integral, then the matter of overloading 
 with long, conversion from literals 1 and 0 etc. may be 
 reopened. Even then, it would be a difficult decision.
I agree with most of what you said in your full post, except that in the quote above you are suggesting that there's a difficult decision to be made in the case of bool being it's own type rather than an integral type. The opposite should be the case, where the decision to keep it as an integral is a difficult to defend. I don't see where the difficulty is, because unless bool can exactly be treated as an integral, then it simply is not an integral, and unless it is an integral, it cannot be freely interchanged with the integrals. The arguments in defense if bool as an integral are IMO weak. For example, Walter mentioned the case of char successfully being treated as an integral type rather than a special case "char' type. However, are there any differences between what char does and what byte does that interfere with each other? If char performs exactly like a integral type, then you can convincingly argue that it is an integral type. Can the same thing with char be said about bool? No. You can only say that bool does share some, but not all the characteristics if an integral. The other argument in favor boils down to a matter of convenience under some circumstances. Yes, there are a few cases where it is advantageous to interchange boolean 'true' and 'false' with integral 1 and 0, however the vast majority of uses do not rely on such an interchange, and even if such interchanges are used often, bool still has significant differences of behavior that exclude it from being considered as a fully interchangeable integral type (eg truncation behavior and differences with operators). The best you can argue for, is that under some situations, bool should be freely interchanged with regular integrals, however that's not going to be true for all cases. The conclusion ought to be that unless bool can be adjusted into behaving exactly like all the other integrals, then it simply cannot be freely interchanged as an integral in all cases, i.e., maybe OK in some cases, but certainly not all. --rt
Apr 29 2013
prev sibling parent kenji hara <k.hara.pg gmail.com> writes:
A real issue against disallowing 0/1 to bool conversion is in the
translation code from C/C++ to D.

For example, old C code may have thus macro constant.
#define FALSE 0
#define TRUE 1
#define BOOL  int
void foo(BOOL flag);
foo(FALSE);

Translating the code to D:
enum FALSE = 0;
enum TRUE = 1;
alias BOOL = int;
void foo(BOOL flag);
foo(FALSE);

And then, we can misuse FALSE and TRUE.

void bar(bool flag);
bar(FALSE);   // int argument FALSE(==0) now matches to bool

This is enough realistic case. We already have an actual case in
core.sys.windows.windows:

    enum : int
    {
        FALSE = 0,
        TRUE = 1,
    }

And core sys windows.stacktrace:

    if (!dbghelp.SymInitialize(hProcess, generateSearchPath().ptr, TRUE))
        return;
(dbghelp.SymInitialize is a function pointer that defined as
    alias BOOL         function(HANDLE hProcess, PCSTR UserSearchPath, bool
fInvadeProcess) SymInitializeFunc;

    struct DbgHelp
    {
        SymInitializeFunc        SymInitialize;
        ...
    }
)

If we change the behavior, we should accept the existing code break.

Kenji Hara
Apr 27 2013
prev sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
(This is a quotation from
http://d.puremagic.com/issues/show_bug.cgi?id=9999<http://d.puremagic.com/issues/show_bug.cgi?id=9999#c4>
)

 I do not agree with this enhancement. First off, making special cases for
 partial ordering takes a simple, straightforward idea and turns it into a
 potential morass of conflicting cases that we'll be stuck with forever.
 Secondly, the only issue here is whether '1' should be implicitly
convertible
 to 'bool'.
Walter, I can understand your concern. But I think it would not be so big. Because the possibility of extending basic type set is not so much in the future. Keeping language spec simple is necessary, but also reduce special rule for humans is also important. This is a much rare case that is the mismatch between simple rule and natural behavior for human. Fixing this issue would be valuable for many D users. Logically 'true' and 'false' are not related to any integer values. Although it is widely known and used, considering boolean type as a kind of specialized integer type is not general - it is implementation detail. At least it comes from C language. In old ages, boolean type had not been supported properly in many programming languages, but today, languages which not supporting it would not regarded as useful. D is a modern programming language, so more proper behavior for boolean type is necessary. As one of its goal, D should aim the successor of C. Therefore, we cannot drop the implicit conversion between bool and other integer types which inherited from C. But this problem behavior is definitely unnatural for many programmers, and would enforce to study bad know-how for them. Loosing future users for the compiler simplicity is not good decision. Of course, balance is necessary there, but I think this is necessary complexity. Kenji Hara 2013/4/28 kenji hara <k.hara.pg gmail.com>
 2013/4/28 Walter Bright <newshound2 digitalmars.com>

 On 4/27/2013 8:11 AM, kenji hara wrote:

 Walter, now I changed my opinion. It seems not correct that being
 regarded bool
 type as one of the integer.
 How about?
Both C and C++ regard bool as an integer, and implicitly convert 1/0 to true/false. What C++ doesn't have is VRP and partial ordering of functions. (But it does have partial ordering of template functions.)
I'm not argue that we should remove the implicit conversion from 1/0 to bool. I don't have so much knowledge about C/C++ language spec, but for the issue case C++ makes "ambiguous error". Contrary of that, D's current behavior looks to me it is going back to past. Kenji Hara
Apr 27 2013
parent "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
VRP is only useful when doing this:

short s = 1000; // 1000 is int, but it's safe to put it into a 
short

Integers are not booleans. I agree with the others that bool 
being treated as an int is an implementation detail derived from 
C.

Or are you just bored for doing:
if( x == 0 )

instead of
if( x )

?
Apr 27 2013
prev sibling parent kenji hara <k.hara.pg gmail.com> writes:
I filed the issue in bugzilla, and opened pull request to fix it.

http://d.puremagic.com/issues/show_bug.cgi?id=9999
https://github.com/D-Programming-Language/dmd/pull/1942

Kenji Hara


2013/4/28 kenji hara <k.hara.pg gmail.com>

 OK. I misunderstood.

 C does not allow function overloading, so same problem is not there.
 In C++,

 // test.cpp
 #include <stdio.h>
 void foo(bool) { printf("bool\n"); }
 void foo(long) { printf("long\n"); }
 int main(int argc, char **argv)
 {
 foo(false);  // matches bool version
 foo(true);   // matches bool version
  foo(0);  // ambiguous
 foo(1);  // ambiguous
  foo(2);  // ambiguous
 return 0;
 }

 The behavior is same with GCC 4.7.2 (using msys) and dmc.

 Walter, now I changed my opinion. It seems not correct that being regarded
 bool type as one of the integer.
 How about?

 Kenji Hara

 2013/4/27 Minas Mina <minas_mina1990 hotmail.co.uk>

 On Saturday, 27 April 2013 at 11:41:30 UTC, kenji hara wrote:

 First, I can guess that why Walter disagree *fixing* this problem.

 http://dlang.org/overview.html

 Major Design Goals of D
 9. Where D code looks the same as C code, have it either behave the same
or issue an error.
C doesn't have a bool type, so how can D behave the same?
Apr 27 2013
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/27/13, kenji hara <k.hara.pg gmail.com> wrote:
 // The expected behavior we can do at the most
 extern(C) int printf(const char*, ...);
 void foo(bool) { printf("bool\n"); }
 void foo(long) { printf("long\n"); }
 void main()
 {
   foo(0);  // Error: function foo called with argument types: (int) matches
 both foo(bool) and foo(long)
   foo(1);  // Error: function foo called with argument types: (int) matches
 both foo(bool) and foo(long)
   foo(2);  // OK, matches to long
 }
That's even more stupid. We need *less* special cases, not more. We already have true/false, they're keywords, any other integral literal (*literal*, not expression) should not implicitly convert to bool.
Apr 27 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

 That's even more stupid.
Please be gentle. That from Kenji is one of the few usable ideas of this thread. Bye, bearophile
Apr 27 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 27 April 2013 at 12:20:00 UTC, bearophile wrote:
 Andrej Mitrovic:

 That's even more stupid.
Please be gentle. That from Kenji is one of the few usable ideas of this thread. Bye, bearophile
No, that is even worse.
Apr 27 2013
prev sibling parent reply "Kapps" <opantm2+spam gmail.com> writes:
This is just silly.
Changing enum defaultVal = 1 to defaultVal = 2 should never 
result in calling a different overload.
Apr 25 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/25/2013 7:54 PM, Kapps wrote:
 This is just silly.
 Changing enum defaultVal = 1 to defaultVal = 2 should never result in calling a
 different overload.
This does: ------------------------ import core.stdc.stdio; enum x = 10000; enum y = 40000; int foo(short s) { return 1; } int foo(long s) { return 2; } void main() { printf("%d\n", foo(x)); printf("%d\n", foo(y)); } ------------------------- A bool is an integer with the range 0..1
Apr 25 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/25/2013 10:02 PM, Walter Bright wrote:> On 4/25/2013 7:54 PM, 
Kapps wrote:
 This is just silly.
 Changing enum defaultVal = 1 to defaultVal = 2 should never result in
 calling a
 different overload.
This does: ------------------------ import core.stdc.stdio; enum x = 10000; enum y = 40000; int foo(short s) { return 1; } int foo(long s) { return 2; } void main() { printf("%d\n", foo(x)); printf("%d\n", foo(y)); } ------------------------- A bool is an integer with the range 0..1
It certainly behaves that way but it isn't an integer type and that's why it is unintuitive. bool is a type with two values: false and true with the following conversion rules: false -> 0 true -> 1 0 value -> false non-zero value -> true 0 literal -> false The following are the problematic ones: 1 literal -> true non-zero and non-one *literal* -> Not a bool! That last rule is the problem. Since we cannot get rid of the last rule, to be consistent, we should make literal 1 match an integer type better than bool. Ali
Apr 25 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/25/2013 10:49 PM, Ali Çehreli wrote:
 It certainly behaves that way but it isn't an integer type and that's why it is
 unintuitive.
But it is an integer type.
 bool is a type with two values: false and true with the following conversion
rules:

 false -> 0
 true -> 1
 0 value -> false
 non-zero value -> true
 0 literal -> false

 The following are the problematic ones:

 1 literal -> true
 non-zero and non-one *literal* -> Not a bool!

 That last rule is the problem. Since we cannot get rid of the last rule, to be
 consistent, we should make literal 1 match an integer type better than bool.
Whether it's a problem or not depends on one's perspective. The next issue is the notion of a "better" match. This notion is very complex in C++, and still produces odd results. Very few people can explain how it works - it's kind of shoot and hope you hit the target. D tries very hard to avoid the notion of a "better" match. It goes with an exact match, followed by one with implicit conversions. All implicit conversions are considered equally good. Ambiguity is resolved by invoking "partial ordering", which was explained elsewhere in this thread. Partial ordering does not at all consider "better" matches. Once you venture down the path of "better" matches, it's all roses at first, but look at where C++ wound up with it. It didn't intend to arrive there, it inevitably arrived there. The real issue is do you want to have the implicit conversions: 0 => false 1 => true or would you require a cast?
Apr 25 2013
next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 06:01:27 UTC, Walter Bright wrote:
 The real issue is do you want to have the implicit conversions:

 0 => false
 1 => true

 or would you require a cast?
Yes.
Apr 25 2013
parent reply "Manipulator" <volcz kth.se> writes:
On Friday, 26 April 2013 at 06:18:29 UTC, deadalnix wrote:
 On Friday, 26 April 2013 at 06:01:27 UTC, Walter Bright wrote:
 The real issue is do you want to have the implicit conversions:

 0 => false
 1 => true

 or would you require a cast?
Yes.
+1 What about the implicit conversion for the other types? I could imagine that they could cause similar bugs. Why not get rid of the implicit conversion? How about yet another compiler flag?
Apr 25 2013
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/25/2013 11:42 PM, Manipulator wrote:
 What about the implicit conversion for the other types? I could imagine that
 they could cause similar bugs. Why not get rid of the implicit conversion?
Implicit conversions make the menagerie of integer types tractable. Explicit casts are a sledgehammer that often causes bugs rather than eliminates them.
 How about yet another compiler flag?
Compiler flags that alter the meaning of the language are not the solution.
Apr 26 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 06:42:28 UTC, Manipulator wrote:
 On Friday, 26 April 2013 at 06:18:29 UTC, deadalnix wrote:
 On Friday, 26 April 2013 at 06:01:27 UTC, Walter Bright wrote:
 The real issue is do you want to have the implicit 
 conversions:

 0 => false
 1 => true

 or would you require a cast?
Yes.
+1 What about the implicit conversion for the other types? I could imagine that they could cause similar bugs. Why not get rid of the implicit conversion? How about yet another compiler flag?
No no no no, please no.
Apr 26 2013
prev sibling next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Friday, 26 April 2013 at 06:01:27 UTC, Walter Bright wrote:
 On 4/25/2013 10:49 PM, Ali Çehreli wrote:
 It certainly behaves that way but it isn't an integer type and 
 that's why it is
 unintuitive.
But it is an integer type.
Regarding bool type as integer type is C atavism and should be abandoned. This leads to comic sitatuation presented in the thread when changing literal to lvalue or using different enums changes overloading matching.
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 12:07 AM, Maxim Fomin wrote:
 Regarding bool type as integer type is C atavism and should be abandoned.
There's a very loooong history of 0 being regarded as false and 1 as true - it goes well beyond C.
 This leads to comic sitatuation presented in the thread when changing literal
to
 lvalue or using different enums changes overloading matching.
Yet I showed an analogous example where different overloads were selected based on a different integer value. There's no getting away from having to pay attention when declaring different overloads of a function. In the original example, the correct solution is to provide a foo(int). I'd be suspicious of any code that only had overloads on just bool and long - it doesn't make sense.
Apr 26 2013
next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Friday, 26 April 2013 at 08:00:28 UTC, Walter Bright wrote:
 On 4/26/2013 12:07 AM, Maxim Fomin wrote:
 Regarding bool type as integer type is C atavism and should be 
 abandoned.
There's a very loooong history of 0 being regarded as false and 1 as true - it goes well beyond C.
This should be irrelevant in case of long parameter. Such conversion should not be in the language (like feature of array to pointer conversion and function to pointer to function conversion is present in C but not in D).
 This leads to comic sitatuation presented in the thread when 
 changing literal to
 lvalue or using different enums changes overloading matching.
Yet I showed an analogous example where different overloads were selected based on a different integer value. There's no getting away from having to pay attention when declaring different overloads of a function. In the original example, the correct solution is to provide a foo(int). I'd be suspicious of any code that only had overloads on just bool and long - it doesn't make sense.
I argue the correct solution is to call integer function with integer parameter when integer value is passed. Adjusting to buggy compiler behavior isn't a good idea.
Apr 26 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 1:14 AM, Maxim Fomin wrote:
 I argue the correct solution is to call integer function with integer parameter
 when integer value is passed.
I'm sorry, but that's an assertion not an argument. The other issue with your assertion, as I explained to Ali, is that D does not have a notion of "better" implicit conversions, and it would be a tragedy to add them.
 Adjusting to buggy compiler behavior isn't a good idea.
It's working as designed - it is not a compiler bug.
Apr 26 2013
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Friday, 26 April 2013 at 08:00:28 UTC, Walter Bright wrote:
 On 4/26/2013 12:07 AM, Maxim Fomin wrote:
 Regarding bool type as integer type is C atavism and should be 
 abandoned.
There's a very loooong history of 0 being regarded as false and 1 as true - it goes well beyond C.
Assembly, PL/I, Algol, ...? Just asking as a language geek. Personally, given my strong typing background, I dislike the automatic conversion to booleans. Even my C code has explicit comparisons for NULL pointers, instead of relying in implicit conversions. -- Paulo
Apr 26 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 08:00:28 UTC, Walter Bright wrote:
 On 4/26/2013 12:07 AM, Maxim Fomin wrote:
 Regarding bool type as integer type is C atavism and should be 
 abandoned.
There's a very loooong history of 0 being regarded as false and 1 as true - it goes well beyond C.
That is true, but even in theses elder languages, bool is handled as a special case, and not as an regular integral type. For instance, when integral conversion to smaller type is done by applying a mask (or doing a modulo, this is the same thing in this case) it is done by comparing to 0 to compare to bool.
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 7:33 AM, deadalnix wrote:
 On Friday, 26 April 2013 at 08:00:28 UTC, Walter Bright wrote:
 On 4/26/2013 12:07 AM, Maxim Fomin wrote:
 Regarding bool type as integer type is C atavism and should be abandoned.
There's a very loooong history of 0 being regarded as false and 1 as true - it goes well beyond C.
That is true, but even in theses elder languages, bool is handled as a special case, and not as an regular integral type. For instance, when integral conversion to smaller type is done by applying a mask (or doing a modulo, this is the same thing in this case) it is done by comparing to 0 to compare to bool.
I've also spent time with embedded systems that manipulated things by writing out 0's and 1's to ports, designed ABEL (a language for programming PLDs), and simply worked a lot with digital math. 0 and 1 being synonymous with false and true is deeply embedded. A bool is a one bit integer. I remember once a language that tried to define true and false as something other than 1 and 0. It was horrible.
Apr 26 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
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.
Apr 26 2013
parent reply "Rob T" <alanb ucora.com> writes:
On Saturday, 27 April 2013 at 01:37:22 UTC, deadalnix wrote:
 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.
D can still cast true to 1 and false to 0. It is solely the implicit casting that is inappropriate under rather common circumstances. --rt
Apr 26 2013
parent reply =?UTF-8?B?Ikx1w61z?= Marques" <luismarques gmail.com> writes:
Is this what some of you are asking for?

bool a = true;             // ok
bool b = false;            // ok
bool c = 1;                 // error, no implicit conversion
bool c = getInt();        // error? ok?
int x = 42;
if(x) { ... }                   // ok (doesn't this imply c = 
getInt() ok too?
if(42) { ... }                 // ok
Apr 26 2013
next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Saturday, 27 April 2013 at 05:54:48 UTC, Luís Marques wrote:
 Is this what some of you are asking for?

 bool a = true;             // ok
Yes
 bool b = false;            // ok
Yes
 bool c = 1;                 // error, no implicit conversion
Yes
 bool c = getInt();        // error? ok?
Yes (error)
 int x = 42;
 if(x) { ... }                   // ok (doesn't this imply c =
Yes
 getInt() ok too?
Yes
 if(42) { ... }                 // ok
Yes
Apr 26 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 27 April 2013 at 05:54:48 UTC, Luís Marques wrote:
 Is this what some of you are asking for?

 bool a = true;             // ok
 bool b = false;            // ok
 bool c = 1;                 // error, no implicit conversion
 bool c = getInt();        // error? ok?
Last 2 are error.
 int x = 42;
 if(x) { ... }                   // ok (doesn't this imply c = 
 getInt() ok too?
 if(42) { ... }                 // ok
if insert a cast already, so all are ok.
Apr 27 2013
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 27, 2013 07:54:44 =?UTF-8?B?Ikx1w61z?=.Marques 
<luismarques gmail.com> puremagic.com wrote:
 Is this what some of you are asking for?
 
 bool a = true;             // ok
 bool b = false;            // ok
 bool c = 1;                 // error, no implicit conversion
 bool c = getInt();        // error? ok?
 int x = 42;
 if(x) { ... }                   // ok (doesn't this imply c =
 getInt() ok too?
 if(42) { ... }                 // ok
if conditions and loop conditions automatically insert explicit casts, so if(foo) becomes if(cast(bool)foo) which makes it so that you can define how a user-defined type will be treated when used in a condition and for built-in types completely removes if statements and loops from discussions on implicit conversion as there's no implicit conversion being used (unless you're arguing for the cast to not be inserted for conditions, in which case, implicit conversion _would_ be used). - Jonathan M Davis
Apr 27 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/27/2013 5:53 PM, Jonathan M Davis wrote:
 which makes it so that you can define how a user-defined type will be treated
 when used in a condition and for built-in types completely removes if
 statements and loops from discussions on implicit conversion as there's no
 implicit conversion being used (unless you're arguing for the cast to not be
 inserted for conditions, in which case, implicit conversion _would_ be used).
I can't make heads or tails of this!
Apr 28 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2013 09:16 PM, Walter Bright wrote:
 On 4/27/2013 5:53 PM, Jonathan M Davis wrote:
 which makes it so that you can define how a user-defined type will be
 treated
 when used in a condition and for built-in types completely removes if
 statements and loops from discussions on implicit conversion as
 there's no
 implicit conversion being used (unless you're arguing for the cast to
 not be
 inserted for conditions, in which case, implicit conversion _would_ be
 used).
I can't make heads or tails of this!
He is saying that VRP is irrelevant in a boolean evaluation context.
Apr 28 2013
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 28, 2013 12:16:58 Walter Bright wrote:
 On 4/27/2013 5:53 PM, Jonathan M Davis wrote:
 which makes it so that you can define how a user-defined type will be
 treated when used in a condition and for built-in types completely
 removes if statements and loops from discussions on implicit conversion
 as there's no implicit conversion being used (unless you're arguing for
 the cast to not be inserted for conditions, in which case, implicit
 conversion _would_ be used).
I can't make heads or tails of this!
I mean that if conditions and loop conditions have nothing to do with implicit conversions, because an explicit cast is inserted for them by the compiler. So, if you're discussing implicit conversions, conditions really have nothing to do with what's being discussed - _unless_ you're arguing that if statements and loops should use an implicit conversion instead of inserting an explicit cast. The poster I was replying to was lumping in examples of if conditions and loop conditions with examples of implicit conversions. - Jonathan M Davis
Apr 28 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2013 5:19 PM, Jonathan M Davis wrote:
 I mean that if conditions and loop conditions have nothing to do with implicit
 conversions, because an explicit cast is inserted for them by the compiler.
 So, if you're discussing implicit conversions, conditions really have nothing
 to do with what's being discussed - _unless_ you're arguing that if statements
 and loops should use an implicit conversion instead of inserting an explicit
 cast. The poster I was replying to was lumping in examples of if conditions
 and loop conditions with examples of implicit conversions.
Ok, that's better!
Apr 28 2013
prev sibling next sibling parent "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
On Friday, 26 April 2013 at 06:01:27 UTC, Walter Bright wrote:
 On 4/25/2013 10:49 PM, Ali Çehreli wrote:
 It certainly behaves that way but it isn't an integer type and 
 that's why it is
 unintuitive.
But it is an integer type.
It is an integral type _internally_. A bool type should have the values true/false. When someone sees foo(45) he expects it to call an overload that receives an _integral_ value. Which overload is going to be called is a detail (short or long in this example). It is confusing to call an overload that takes bool. Boolean are true/false, not 0, 1 or anything else.
Apr 26 2013
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, April 25, 2013 23:01:30 Walter Bright wrote:
 On 4/25/2013 10:49 PM, Ali Çehreli wrote:
 It certainly behaves that way but it isn't an integer type and that's why
 it is unintuitive.
But it is an integer type.
That was one of C's big mistakes. There's nothing whatsoever about bool that makes sense as an integral type. true and false have nothing to do with 1 and 0 or any other integeral values. Having non-boolean values such as 1 and 0 implicitly convert to bool under some set of circumstances can be very useful (which is why cast(bool) is implicitly used in conditions), but in the general case, it just causes bugs.
 The real issue is do you want to have the implicit conversions:
 
 0 => false
 1 => true
 
 or would you require a cast?
Emphatically yes. The main place where casting would be annoying - if conditions and loop conditions - already insert an explicit cast underneat the hood. Other cases should require explicit casts; otherwise, we're just going to have bugs as has already been pointed out in this thread and has come up a number of times previously in the newsroup (one of the favorites being "foo" ~ true). - Jonathan M Davis
Apr 26 2013
next sibling parent "Rob T" <alanb ucora.com> writes:
On Friday, 26 April 2013 at 19:37:48 UTC, Jonathan M Davis wrote:
 The main place where casting would be annoying - if conditions 
 and loop
 conditions - already insert an explicit cast underneat the hood.
IMO it still makes no sense to have the implicit casting done in conditional statements because it is not obvious why a given conditional should treat a zero differently than all other values. However at this stage retaining that old convention is perhaps unavoidable. At the very least, D should be minimizing the potential for programmers falling into the traps caused by non-intuitive implicit casting. In the case of bool, there's no obvious relationship with the int data type, so let's get rid of that arbitrary association, make casting explicit, and move on. --rt
Apr 26 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Apr 26 2013
next sibling parent "Andrej Mitrovic" <andrej.mitrovich gmail.com> writes:
On Friday, 26 April 2013 at 21:14:54 UTC, Walter Bright wrote:
 A bool is a 1 bit integer type.
.sizeof returns bytes, not bits, and says that bool is of size 1.
Apr 26 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Friday, 26 April 2013 at 21:14:54 UTC, 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:
Uh, uh, that's not a bool. It is a bit (binary digit, just to be sure). That is: a figure of the base 2. The very definition of bit. I still have to see some computer course introducing a byte/octet as a group of 8... booleans. No: boolean is a logical entity and is true or false, while the bit is a figure (a number) and is 0 or 1. They may overlay for programming purposes to some extent (a bijection, after all), but let's not take the one for another. Why the computer theory invented the notion of bit? The term of "boolean" was available for centuries.
Apr 26 2013
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
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
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 3:28 PM, Jonathan M Davis wrote:
 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.
It's not any different from how char is treated (char is also treated as an integer type).
 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.
In general, D treats bool, char, wchar, and dchar as integer types. D also follows the C practice of unadorned integer literals being typed as ints, and the C practice of default integral promotions. If you're not aware of this, yes, you can get surprised when working with overloads across those types. The solution in the antecedent's particular case is to add an overload foo(int), which will neatly prevent any unadorned integer literals from being implicitly cast to char or bool or whatever. It's also a good practice in that unnecessarily promoting ints to longs is a bit of an efficiency issue. [Generally, I'd raise a red flag on any code that only provided foo(bool) and foo(long) overloads.]
 However, we are clearly coming from very different points of view
 here.
Thanks for understanding my point that this is not a right or wrong issue, but a matter of perspective.
Apr 27 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 27, 2013 13:16:55 Walter Bright wrote:
 In general, D treats bool, char, wchar, and dchar as integer types. D also
 follows the C practice of unadorned integer literals being typed as ints,
 and the C practice of default integral promotions.
 
 If you're not aware of this, yes, you can get surprised when working with
 overloads across those types.
Yes, but I honestly think that that's problem too. I think that there's more of an argument for treating characters as integral types than bool, as they really do hold an encoded number internally, but they really aren't treated as integers in general, and I think that treating them as integers implicitly tends to cause problems when conversions come into play. True, it's nice to not have to cast '0' - 42 when assigning it back to a char, but I also don't think that it's all that big a deal for the cast to be required, and I think that allowing things like "foo" ~ 42 is just asking for bugs, particularly when you can easily do something like \u0042 if you actually want a numberic character literal. "foo" ~ true just so happens to be an extreme case of this, as it clearly makes no sense, and if it happens with variables rather than literals, it's not necessarily as obvious that it's happening. We need to be careful with how strongly stuff is typed, because we don't want to require casts everywhere, as that can introduce other types of bugs because casts are so blunt - which is why not requiring casting when converting between int and uint is probably ultimately a good idea - but characters and bool really aren't integral types, even if they do have a relation to them, and I firmly believe that treating them as integral types implicitly causes more bugs than it fixes.
 The solution in the antecedent's particular case is to add an overload
 foo(int), which will neatly prevent any unadorned integer literals from
 being implicitly cast to char or bool or whatever. It's also a good
 practice in that unnecessarily promoting ints to longs is a bit of an
 efficiency issue.
 
 [Generally, I'd raise a red flag on any code that only provided foo(bool)
 and foo(long) overloads.]
Clearly, with how the language currently works, that should raise a red flag, but I think that it's clear that the majority of us would have expected foo(bool) to work with bools, and foo(long) to deal with integral values, allowing you to just have two overloads rather than several.
 However, we are clearly coming from very different points of view
 here.
Thanks for understanding my point that this is not a right or wrong issue, but a matter of perspective.
It is definitely a matter of perspective, but I also think that it's fairly clear that most people here don't expect bool to be treated as an integral type and don't like the fact that it is. If it's truly an integral type, why have true and false in the first place? Why not just use 1 and 0? It seems like implicit casting is making it so that there's no real difference between them, and C++ introduced a bool type rather than sticking with C's approach in order to be able to distinguish between bools and integers when overloading. We appear to be doing a poor job of that. - Jonathan M Davis
Apr 27 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/27/2013 5:49 PM, Jonathan M Davis wrote:
 Yes, but I honestly think that that's problem too. I think that there's more
 of an argument for treating characters as integral types than bool, as they
 really do hold an encoded number internally, but they really aren't treated as
 integers in general, and I think that treating them as integers implicitly
 tends to cause problems when conversions come into play.
Are you really solving a problem, or just creating new ones? I'd rather have a small set of simple, easily explained rules and accept a few issues with them than have a bewildering set of complicated rules trying to solve every problem.
 True, it's nice to not have to cast '0' - 42 when assigning it back to a char,
 but I also don't think that it's all that big a deal for the cast to be
 required,
I've used languages enough that did require such casts. It left an enduring bad taste.
 and I think that allowing things like "foo" ~ 42 is just asking for
 bugs, particularly when you can easily do something like \u0042 if you
 actually want a numberic character literal. "foo" ~ true just so happens to be
 an extreme case of this, as it clearly makes no sense, and if it happens with
 variables rather than literals, it's not necessarily as obvious that it's
 happening.

 We need to be careful with how strongly stuff is typed, because we don't want
 to require casts everywhere, as that can introduce other types of bugs because
 casts are so blunt - which is why not requiring casting when converting
 between int and uint is probably ultimately a good idea - but characters and
 bool really aren't integral types, even if they do have a relation to them,
 and I firmly believe that treating them as integral types implicitly causes
 more bugs than it fixes.
And I just as firmly believe they really are integral types. After all, we constantly manipulate them as integral types: 1. changing case 2. using them as array indices 3. doing utf encoding and decoding 4. generating hashes 5. sorting 6. encoding and decoding integer strings (printf/scanf) 7. compression/decompression 8. encryption/decryption In fact, treating a char as a "character" actually seems to be in the minority of uses!
 Clearly, with how the language currently works, that should raise a red flag,
 but I think that it's clear that the majority of us would have expected
 foo(bool) to work with bools, and foo(long) to deal with integral values,
 allowing you to just have two overloads rather than several.
I don't think it is fundamentally different from the char issue.
 It is definitely a matter of perspective, but I also think that it's fairly
 clear that most people here don't expect bool to be treated as an integral
 type and don't like the fact that it is. If it's truly an integral type, why
 have true and false in the first place? Why not just use 1 and 0?
As history has amply shown, people simply like the true & false literals, and if we didn't supply them, they'd add them to their code in a multitude of incompatible ways (this was a considerable nuisance in C).
 It seems like
 implicit casting is making it so that there's no real difference between them,
 and C++ introduced a bool type rather than sticking with C's approach in order
 to be able to distinguish between bools and integers when overloading. We
 appear to be doing a poor job of that.
There is a place for a 1 bit integer type, and bool fills that role nicely. That doesn't mean it isn't an integer, it's just a boundary case of integers.
Apr 28 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 21:14:54 UTC, 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.
Then why does it convert from int by comparing with 0 ? That isn't the behavior of an integral.
Apr 26 2013
parent "Mehrdad" <wfunction hotmail.com> writes:
On Saturday, 27 April 2013 at 01:43:12 UTC, deadalnix wrote:
 On Friday, 26 April 2013 at 21:14:54 UTC, 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.
Then why does it convert from int by comparing with 0 ? That isn't the behavior of an integral.
+1
Apr 26 2013
prev sibling next sibling parent reply "Brian Schott" <briancschott gmail.com> writes:
On Friday, 26 April 2013 at 06:01:27 UTC, Walter Bright wrote:
 The real issue is do you want to have the implicit conversions:

 0 => false
 1 => true

 or would you require a cast?
The idea of a "true number" and a "false number" doesn't make sense, so yes.
Apr 26 2013
parent reply "Tove" <tove fransson.se> writes:
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:
 The real issue is do you want to have the implicit conversions:

 0 => false
 1 => true

 or would you require a cast?
The idea of a "true number" and a "false number" doesn't make sense, so yes.
I find the current implementation perfectly intuitive and I wouldn´t want it any other way... it models the underlying hardware, just the way it should be. 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. doesn´t matter how many years, I was forced to do it, I still cringe every time I see a line like that and itch to rewrite it more readable. I also dont know any book(including Knuth), nor online article, which doesn´t clearly define it as 0,1... am very confused by the reactions in this thread, is my background so different from everyone elses?
Apr 26 2013
next sibling parent "eles" <eles eles.com> writes:
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.
Apr 26 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
Apr 26 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
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:
 The real issue is do you want to have the implicit 
 conversions:

 0 => false
 1 => true

 or would you require a cast?
The idea of a "true number" and a "false number" doesn't make sense, so yes.
I find the current implementation perfectly intuitive and I wouldn´t want it any other way... it models the underlying hardware, just the way it should be. 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. doesn´t matter how many years, I was forced to do it, I still cringe every time I see a line like that and itch to rewrite it more readable.
That is totally irrelevant as a cast is already inserted automatically.
Apr 26 2013
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 25 Apr 2013 23:01:30 -0700, Walter Bright  
<newshound2 digitalmars.com> wrote:

 D tries very hard to avoid the notion of a "better" match. It goes with  
 an exact match, followed by one with implicit conversions. All implicit  
 conversions are considered equally good. Ambiguity is resolved by  
 invoking "partial ordering", which was explained elsewhere in this  
 thread. Partial ordering does not at all consider "better" matches.
I think the issue (and I am firmly in the foo(1) => long camp) is that bools are considered better integers than actual integer types (or even floating point types for that matter). I agree that bools can be implicitly cast to and from integers, as a last resort.
 Once you venture down the path of "better" matches, it's all roses at  
 first, but look at where C++ wound up with it. It didn't intend to  
 arrive there, it inevitably arrived there.
bool is true or false. It can be interchangeable with 0 or 1. But if it's overloaded with an integral or otherwise numeric type (float, double, etc), then the numeric type should be chosen first, or ambiguity flagged (your choice). The current behavior is as bad as if(); That's not ambiguous, and follows the grammatical rules, why does that deserve a special case and this not?
 The real issue is do you want to have the implicit conversions:

 0 => false
 1 => true

 or would you require a cast?
This is irrelevant to the problem. If one wants to pass a boolean literal, they would use true or false, not cast(bool)1 or cast(bool)0. When an implicit cast must be done, and overload selection is at stake, bool should be last on the list of numeric types. I think you are incorrectly making this into a "it has to be this way for consistency" issue, it's not. It's an arbitrary rule, with very little sense involved. -Steve
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 11:04 PM, Steven Schveighoffer wrote:
 I think the issue (and I am firmly in the foo(1) => long camp) is that bools
are
 considered better integers than actual integer types (or even floating point
 types for that matter).  I agree that bools can be implicitly cast to and from
 integers, as a last resort.
The overload system in D is explicitly not based on "better". (The C++ "better" overloading system is for functions, but not for templates.) The D overload system is based on partial ordering, which is the same as what C++ uses for templates. I don't know for a fact, but I'm pretty sure the partial ordering scheme that C++ selected for templates, which came along many years later, was picked because people realized it was better (and more mathematically robust and defensible). One of the problems with a "better" matching system is handling functions with multiple parameters, each with their own "better" match. (The C++ Standard devotes a great deal of complex text to this, it boils down to a bunch of rather arbitrary decisions.) Partial ordering solves this neatly and consistently. As one who implemented C++'s better matching system, I can confidently state that the partial ordering scheme is FAR better overall.
Apr 27 2013
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 27 Apr 2013 13:27:39 -0700, Walter Bright  
<newshound2 digitalmars.com> wrote:

 On 4/26/2013 11:04 PM, Steven Schveighoffer wrote:
 I think the issue (and I am firmly in the foo(1) => long camp) is that  
 bools are
 considered better integers than actual integer types (or even floating  
 point
 types for that matter).  I agree that bools can be implicitly cast to  
 and from
 integers, as a last resort.
The overload system in D is explicitly not based on "better". (The C++ "better" overloading system is for functions, but not for templates.) The D overload system is based on partial ordering, which is the same as what C++ uses for templates. I don't know for a fact, but I'm pretty sure the partial ordering scheme that C++ selected for templates, which came along many years later, was picked because people realized it was better (and more mathematically robust and defensible). One of the problems with a "better" matching system is handling functions with multiple parameters, each with their own "better" match. (The C++ Standard devotes a great deal of complex text to this, it boils down to a bunch of rather arbitrary decisions.) Partial ordering solves this neatly and consistently. As one who implemented C++'s better matching system, I can confidently state that the partial ordering scheme is FAR better overall.
I think you are inventing a strawman problem that this bug solves. There is no need for a "Better" scheme, partial ordering works great, and so do true and false. bool isn't an integer. It can implicitly cast to an integer, but that's it. Once we implement that rule, everything falls into place. If you want to pass a "true" boolean literal, use true. If you want to pass a "false" boolean literal use false. Using 1 and 0 may be convenient, and may also be valid, but when it matches an integral type as well as bool, then it's ambiguous. -Steve
Apr 29 2013
next sibling parent Paulo Pinto <pjmlp progtools.org> writes:
Am 29.04.2013 19:10, schrieb Steven Schveighoffer:
 On Sat, 27 Apr 2013 13:27:39 -0700, Walter Bright
 <newshound2 digitalmars.com> wrote:

 On 4/26/2013 11:04 PM, Steven Schveighoffer wrote:
 I think the issue (and I am firmly in the foo(1) => long camp) is
 that bools are
 considered better integers than actual integer types (or even
 floating point
 types for that matter).  I agree that bools can be implicitly cast to
 and from
 integers, as a last resort.
The overload system in D is explicitly not based on "better". (The C++ "better" overloading system is for functions, but not for templates.) The D overload system is based on partial ordering, which is the same as what C++ uses for templates. I don't know for a fact, but I'm pretty sure the partial ordering scheme that C++ selected for templates, which came along many years later, was picked because people realized it was better (and more mathematically robust and defensible). One of the problems with a "better" matching system is handling functions with multiple parameters, each with their own "better" match. (The C++ Standard devotes a great deal of complex text to this, it boils down to a bunch of rather arbitrary decisions.) Partial ordering solves this neatly and consistently. As one who implemented C++'s better matching system, I can confidently state that the partial ordering scheme is FAR better overall.
I think you are inventing a strawman problem that this bug solves. There is no need for a "Better" scheme, partial ordering works great, and so do true and false. bool isn't an integer. It can implicitly cast to an integer, but that's it. Once we implement that rule, everything falls into place. If you want to pass a "true" boolean literal, use true. If you want to pass a "false" boolean literal use false. Using 1 and 0 may be convenient, and may also be valid, but when it matches an integral type as well as bool, then it's ambiguous. -Steve
Fully agree, I still not understand what is the issue to support the boolean strong typing other languages do offer. -- Paulo
Apr 29 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/29/2013 10:10 AM, Steven Schveighoffer wrote:
 On Sat, 27 Apr 2013 13:27:39 -0700, Walter Bright <newshound2 digitalmars.com>
 wrote:

 On 4/26/2013 11:04 PM, Steven Schveighoffer wrote:
 I think the issue (and I am firmly in the foo(1) => long camp) is that bools
are
 considered better integers than actual integer types (or even floating point
 types for that matter).  I agree that bools can be implicitly cast to and from
 integers, as a last resort.
The overload system in D is explicitly not based on "better". (The C++ "better" overloading system is for functions, but not for templates.) The D overload system is based on partial ordering, which is the same as what C++ uses for templates. I don't know for a fact, but I'm pretty sure the partial ordering scheme that C++ selected for templates, which came along many years later, was picked because people realized it was better (and more mathematically robust and defensible). One of the problems with a "better" matching system is handling functions with multiple parameters, each with their own "better" match. (The C++ Standard devotes a great deal of complex text to this, it boils down to a bunch of rather arbitrary decisions.) Partial ordering solves this neatly and consistently. As one who implemented C++'s better matching system, I can confidently state that the partial ordering scheme is FAR better overall.
I think you are inventing a strawman problem that this bug solves. There is no need for a "Better" scheme, partial ordering works great, and so do true and false. bool isn't an integer. It can implicitly cast to an integer, but that's it. Once we implement that rule, everything falls into place. If you want to pass a "true" boolean literal, use true. If you want to pass a "false" boolean literal use false. Using 1 and 0 may be convenient, and may also be valid, but when it matches an integral type as well as bool, then it's ambiguous.
Carefully reading your statement, you are still arguing that matching 1 to long should be "better" than matching it to bool.
Apr 29 2013
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 29 Apr 2013 11:39:27 -0700, Walter Bright  
<newshound2 digitalmars.com> wrote:

 On 4/29/2013 10:10 AM, Steven Schveighoffer wrote:
 I think you are inventing a strawman problem that this bug solves.   
 There is no
 need for a "Better" scheme, partial ordering works great, and so do  
 true and false.

 bool isn't an integer.  It can implicitly cast to an integer, but  
 that's it.
 Once we implement that rule, everything falls into place.  If you want  
 to pass a
 "true" boolean literal, use true.  If you want to pass a "false"  
 boolean literal
 use false.  Using 1 and 0 may be convenient, and may also be valid, but  
 when it
 matches an integral type as well as bool, then it's ambiguous.
Carefully reading your statement, you are still arguing that matching 1 to long should be "better" than matching it to bool.
Yes, just like it's better matching to long than string. -Steve
Apr 30 2013
parent reply "Rob T" <alanb ucora.com> writes:
On Tuesday, 30 April 2013 at 14:47:14 UTC, Steven Schveighoffer 
wrote:
 Yes, just like it's better matching to long than string.

 -Steve
More precise language is to state that there is no "better match" and long should simply not ever match with bool because long is not the same thing as bool, ie, bool should not be seen as an integral type because it clearly isn't because it does not behave like one and has a completely different purpose in the language otherwise there'd be no need for a bool to have special differences that the other integrals do not have. How do we get the problem fixed? The sooner it is done the better, otherwise we'll be forever stuck with subtle bugs and D programmers complaining about it for the rest of eternity. --rt
Apr 30 2013
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 30 Apr 2013 10:43:01 -0700, Rob T <alanb ucora.com> wrote:

 On Tuesday, 30 April 2013 at 14:47:14 UTC, Steven Schveighoffer wrote:
 Yes, just like it's better matching to long than string.

 -Steve
More precise language is to state that there is no "better match" and long should simply not ever match with bool because long is not the same thing as bool, ie, bool should not be seen as an integral type because it clearly isn't because it does not behave like one and has a completely different purpose in the language otherwise there'd be no need for a bool to have special differences that the other integrals do not have. How do we get the problem fixed? The sooner it is done the better, otherwise we'll be forever stuck with subtle bugs and D programmers complaining about it for the rest of eternity.
1. bool doesn't match to 1 or 0. 2. cast(bool)0 -> false 3. cast(bool)(anything but 0) -> true 4. true -> (implicit cast) 1 5. false -> (implicit cast) 0. Then all that is left is to change any place where 1 or 0 implicitly casts to true or false to true and false. The one casualty is any code that passes 1 or 0 to a function overloaded with long, short, or byte (or unsigned versions), and bool, will now silently switch to calling the integral version. I would posit that this is extremely rare. -Steve
Apr 30 2013
parent reply Paulo Pinto <pjmlp progtools.org> writes:
Am 30.04.2013 20:50, schrieb Steven Schveighoffer:
 On Tue, 30 Apr 2013 10:43:01 -0700, Rob T <alanb ucora.com> wrote:

 On Tuesday, 30 April 2013 at 14:47:14 UTC, Steven Schveighoffer wrote:
 Yes, just like it's better matching to long than string.

 -Steve
More precise language is to state that there is no "better match" and long should simply not ever match with bool because long is not the same thing as bool, ie, bool should not be seen as an integral type because it clearly isn't because it does not behave like one and has a completely different purpose in the language otherwise there'd be no need for a bool to have special differences that the other integrals do not have. How do we get the problem fixed? The sooner it is done the better, otherwise we'll be forever stuck with subtle bugs and D programmers complaining about it for the rest of eternity.
1. bool doesn't match to 1 or 0. 2. cast(bool)0 -> false 3. cast(bool)(anything but 0) -> true 4. true -> (implicit cast) 1 5. false -> (implicit cast) 0. Then all that is left is to change any place where 1 or 0 implicitly casts to true or false to true and false. The one casualty is any code that passes 1 or 0 to a function overloaded with long, short, or byte (or unsigned versions), and bool, will now silently switch to calling the integral version. I would posit that this is extremely rare. -Steve
+1
Apr 30 2013
parent Timothee Cour <thelastmammoth gmail.com> writes:
+1 (and give a helpful compiler error with suggested modification)
Apr 30 2013
prev sibling parent "MattCoder" <mattcoder hotmail.com> writes:
On Monday, 29 April 2013 at 18:39:27 UTC, Walter Bright wrote:
 On 4/29/2013 10:10 AM, Steven Schveighoffer wrote:
 On Sat, 27 Apr 2013 13:27:39 -0700, Walter Bright 
 <newshound2 digitalmars.com>
 wrote:
 .
 . .
 bool isn't an integer.  It can implicitly cast to an integer, 
 but that's it.
 Once we implement that rule, everything falls into place.  If 
 you want to pass a
 "true" boolean literal, use true.  If you want to pass a 
 "false" boolean literal
 use false.  Using 1 and 0 may be convenient, and may also be 
 valid, but when it
 matches an integral type as well as bool, then it's ambiguous.
Carefully reading your statement, you are still arguing that matching 1 to long should be "better" than matching it to bool.
Walter, Don't you agree that the current way can be confusing? For example, the following code generates 2 differents results/output: import std.stdio; void foo(bool b) { writeln("bool"); } void foo(long l) { writeln("long"); } void main() { long num = 0; foo(num); foo(0); foo(2); } output: long bool long Regardless the fact that num is a variable (long), the first 2 foo calls in my perspective means foo(0), and should generate the same output. Don't you agree with that?
Apr 30 2013
prev sibling parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Friday, 26 April 2013 at 06:01:27 UTC, Walter Bright wrote:
 On 4/25/2013 10:49 PM, Ali Çehreli wrote:
 It certainly behaves that way but it isn't an integer type and 
 that's why it is unintuitive.
But it is an integer type.
Walter, you've confused "Boolean arithmetic" with "binary arithmetic". Boolean arithmetic: 1 + 1 = 1 Binary arithmetic: 1 + 1 = 0 "bool" means Boolean value, "bit" means binary integer. The entire confusion in this thread is because you're mixing up the two.
Apr 28 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2013 1:58 PM, Mehrdad wrote:
 The entire confusion in this thread is because you're mixing up the two.
I know exactly what you're talking about, and I haven't seen any confusion from other posters, either.
Apr 28 2013
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Sunday, 28 April 2013 at 21:17:39 UTC, Walter Bright wrote:
 On 4/28/2013 1:58 PM, Mehrdad wrote:
 The entire confusion in this thread is because you're mixing 
 up the two.
I know exactly what you're talking about, and I haven't seen any confusion from other posters, either.
If I just told you why Boolean arithmetic isn't integer arithmetic, and you know exactly what I'm talking about, then why do you say Booleans are integers? Isn't that self-contradictory?
Apr 28 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2013 11:22 PM, Mehrdad wrote:
 On Sunday, 28 April 2013 at 21:17:39 UTC, Walter Bright wrote:
 On 4/28/2013 1:58 PM, Mehrdad wrote:
 The entire confusion in this thread is because you're mixing up the two.
I know exactly what you're talking about, and I haven't seen any confusion from other posters, either.
If I just told you why Boolean arithmetic isn't integer arithmetic, and you know exactly what I'm talking about, then why do you say Booleans are integers? Isn't that self-contradictory?
He is saying bool is an integral type in D. (i.e. it can be promoted to 'int' in order to support integer arithmetic.)
Apr 28 2013
parent reply kenji hara <k.hara.pg gmail.com> writes:
Yes, as Andrei mentioned, it is sometimes useful. But, at least during
overload resolution, it must not occur.

Kenji Hara


2013/4/29 Timon Gehr <timon.gehr gmx.ch>

 On 04/28/2013 11:22 PM, Mehrdad wrote:

 On Sunday, 28 April 2013 at 21:17:39 UTC, Walter Bright wrote:

 On 4/28/2013 1:58 PM, Mehrdad wrote:

 The entire confusion in this thread is because you're mixing up the two.
I know exactly what you're talking about, and I haven't seen any confusion from other posters, either.
If I just told you why Boolean arithmetic isn't integer arithmetic, and you know exactly what I'm talking about, then why do you say Booleans are integers? Isn't that self-contradictory?
He is saying bool is an integral type in D. (i.e. it can be promoted to 'int' in order to support integer arithmetic.)
Apr 28 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/28/13 5:41 PM, kenji hara wrote:
 Yes, as Andrei mentioned, it is sometimes useful. But, at least during
 overload resolution, it must not occur.

 Kenji Hara
Well the problem has other ramifications beyond bool. Consider: import std.stdio; int fun(short v1) { return 1; } int fun(long v1) { return 2; } void main(string[] args) { writeln(fun(10_000)); writeln(fun(100_000)); } This prints "1 2". So the behavior of bool in this case is consistent with the behavior of other integral types. Andrei
Apr 28 2013
next sibling parent reply "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
On Sunday, 28 April 2013 at 22:40:33 UTC, Andrei Alexandrescu 
wrote:
 On 4/28/13 5:41 PM, kenji hara wrote:
 Yes, as Andrei mentioned, it is sometimes useful. But, at 
 least during
 overload resolution, it must not occur.

 Kenji Hara
Well the problem has other ramifications beyond bool. Consider: import std.stdio; int fun(short v1) { return 1; } int fun(long v1) { return 2; } void main(string[] args) { writeln(fun(10_000)); writeln(fun(100_000)); } This prints "1 2". So the behavior of bool in this case is consistent with the behavior of other integral types. Andrei
It's not entirely the same. You provided two overloads of integral types. bool is not integral. And yes, I personally don't like this either, but I could live with it. Buy fun(1) calling the bool overload? It's ridiculous. "Code that looks correct should be correct". fun(1) calling bool overload sure looks and is correct.
Apr 28 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/28/13 6:47 PM, Minas Mina wrote:
 It's not entirely the same. You provided two overloads of integral
 types. bool is not integral.
Well that's what I was saying - it's consistent in the approach that tries to align bool with a 1-bit integral as much as possible. Andrei
Apr 28 2013
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Sunday, 28 April 2013 at 22:40:33 UTC, Andrei Alexandrescu 
wrote:
 int fun(short v1) { return 1; }
 int fun(long v1) { return 2; }
 So the behavior of bool in this case is consistent with the 
 behavior of other integral types.
We all understand that, but in that case, it's the programmer's fault (or intention!) for giving different behavior between the two. In the bool/long case, the programmer is writing perfectly logical code, and it's the compiler that interprets it a weird way. You can see the difference more clearly here: void print(long a, bool newline = false) { write(a); if (newline) writeln(); } void print(bool newline = false) { if (newline) writeln(); } void main() { print(1); print(2); } Are you really going to blame the programmer for expecting this to print 1 2 or are you going to blame the language for not doing so?
Apr 28 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 28 April 2013 at 22:40:33 UTC, Andrei Alexandrescu 
wrote:
 On 4/28/13 5:41 PM, kenji hara wrote:
 Yes, as Andrei mentioned, it is sometimes useful. But, at 
 least during
 overload resolution, it must not occur.

 Kenji Hara
Well the problem has other ramifications beyond bool. Consider: import std.stdio; int fun(short v1) { return 1; } int fun(long v1) { return 2; } void main(string[] args) { writeln(fun(10_000)); writeln(fun(100_000)); } This prints "1 2". So the behavior of bool in this case is consistent with the behavior of other integral types.
For the same reason, both should call the long overload.
Apr 29 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 05:02:50 UTC, Walter Bright wrote:
 On 4/25/2013 7:54 PM, Kapps wrote:
 This is just silly.
 Changing enum defaultVal = 1 to defaultVal = 2 should never 
 result in calling a
 different overload.
This does: ------------------------ import core.stdc.stdio; enum x = 10000; enum y = 40000; int foo(short s) { return 1; } int foo(long s) { return 2; } void main() { printf("%d\n", foo(x)); printf("%d\n", foo(y)); } ------------------------- A bool is an integer with the range 0..1
This "feature" never has been useful to me. It has caused bug. Additionally, the behavior is inconsistent : int i = 1; foo(i); // Don't call the bool version.
Apr 25 2013
next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Friday, 26 April 2013 at 06:16:29 UTC, deadalnix wrote:
 On Friday, 26 April 2013 at 05:02:50 UTC, Walter Bright wrote:
 A bool is an integer with the range 0..1
This "feature" never has been useful to me.
+1
Apr 26 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/25/2013 11:16 PM, deadalnix wrote:
 This "feature" never has been useful to me.
It has been useful to me. So there!
 It has caused bug.
The bug is not providing an overload for int.
 Additionally, the behavior is inconsistent :

 int i = 1;
 foo(i); // Don't call the bool version.
It is not inconsistent - you forgot a foo(int) overload. '1' is an int. If you don't supply and int overload, it must implicitly convert, and those conversions are considered equivalent.
Apr 26 2013
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 26 April 2013 at 08:03:14 UTC, Walter Bright wrote:
 On 4/25/2013 11:16 PM, deadalnix wrote:
 This "feature" never has been useful to me.
It has been useful to me. So there!
 It has caused bug.
The bug is not providing an overload for int.
 Additionally, the behavior is inconsistent :

 int i = 1;
 foo(i); // Don't call the bool version.
It is not inconsistent - you forgot a foo(int) overload. '1' is an int. If you don't supply and int overload, it must implicitly convert, and those conversions are considered equivalent.
Because bool value range should be used as a failover mecanism IMO. And bool shouldn't be considered as an integral.
Apr 26 2013
prev sibling parent reply "Rob T" <alanb ucora.com> writes:
On Friday, 26 April 2013 at 08:03:14 UTC, Walter Bright wrote:
 On 4/25/2013 11:16 PM, deadalnix wrote:
 This "feature" never has been useful to me.
It has been useful to me. So there!
If you want an int to behave like a bool, then by all means go ahead and write the code yourself, I don't want the compiler to do it for me in a silent manner.
 It has caused bug.
The bug is not providing an overload for int.
That kind of nonintuitive requirement is easily overlooked.
 Additionally, the behavior is inconsistent :

 int i = 1;
 foo(i); // Don't call the bool version.
It is not inconsistent - you forgot a foo(int) overload. '1' is an int. If you don't supply and int overload, it must implicitly convert, and those conversions are considered equivalent.
Seriously, let's fix this once and for all. Bool is bool, it's not int and never should have been. I don't understand why we're having this debate. --rt
Apr 26 2013
parent "eles" <eles eles.com> writes:
On Friday, 26 April 2013 at 14:28:59 UTC, Rob T wrote:
 On Friday, 26 April 2013 at 08:03:14 UTC, Walter Bright wrote:
 On 4/25/2013 11:16 PM, deadalnix wrote:
 This "feature" never has been useful to me.
It has been useful to me. So there!
Come on, characters are not an integral type, they are just an ordered and, for that reason, an indexed type. All the usual operations on characters apply to the index behnid (which is given by the ASCII/Unicode representation). You are not adding characters, you are adding indices of those characters and so on. And you make a simple convention to always thing "character" for a givent (integer) index, since the index per se is of no much use without its equivalent representation from the ASCII table. On the same grounds, one could index the values of bool form 4 to 5 and assimilate false for 4 and true for 5, then go with the above convention. There is a difference, however, between the bool and the char here: for the bool you want to go straight from the logical value to a conventional integral value, do not even think about some kind of tabular representation, while for the ASCII representation of char you seem to forget that such kind of a table exists in the first place.
Apr 28 2013
prev sibling parent reply Robert Schadek <realburner gmx.de> writes:
On 04/26/2013 07:02 AM, Walter Bright wrote:
 A bool is an integer with the range 0..1
This is True for the type but for the actual code it looks different. There 0 == false. and everything else is true. import std.stdio; void main() { if(10) { writefln("%d is also true", 10); } } if(value) proberly becomes: cmp value, 0 jne ifblock Anyway, I think no implicit casts would be wonderful, sure everybody would hate it at first but than...
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 5:01 AM, Robert Schadek wrote:
 Anyway, I think no implicit casts would be wonderful, sure everybody
 would hate it at first but than...
I've used a language with no implicit casts. It didn't get better, and I have an enduring dislike of it.
Apr 26 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/26/2013 09:11 PM, Walter Bright wrote:
 On 4/26/2013 5:01 AM, Robert Schadek wrote:
 Anyway, I think no implicit casts would be wonderful, sure everybody
 would hate it at first but than...
I've used a language with no implicit casts. It didn't get better, and I have an enduring dislike of it.
What language? (In my experience it actually gets better.)
Apr 26 2013
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 1:16 PM, Timon Gehr wrote:
 On 04/26/2013 09:11 PM, Walter Bright wrote:
 On 4/26/2013 5:01 AM, Robert Schadek wrote:
 Anyway, I think no implicit casts would be wonderful, sure everybody
 would hate it at first but than...
I've used a language with no implicit casts. It didn't get better, and I have an enduring dislike of it.
What language? (In my experience it actually gets better.)
An early Pascal.
Apr 26 2013
prev sibling parent reply "Diggory" <diggsey googlemail.com> writes:
Whatever the choices are of whether bool is a 1-bit integer or a 
a logical true/false value, this should not happen:
enum e = 1;
void main()
{
    foo(e);  // bool
}

static e = 1;
void main()
{
    foo(e);  // long
}

The reason being that according to the language spec, the 
constant "1" should be an int. Whether or not it implicitly 
converts to a bool, this means that "enum e" should have a type 
of int as well. The actual value shouldn't be taken into account 
when determining which overload to call, only the type should 
matter, and an unknown int value should implicitly convert to a 
long not a bool. Automatic conversion of "1" to bool should only 
be able to happen at the point where the literal is used if at 
all:

enum bool e = 1;

Ideally such an implicit conversion would only apply if it was 
the only possible valid implicit conversion, so this:
foo(1)
Should at least warn of the ambiguity.

Compile-time conversions based on value rather than type are by 
definition going to break the type system. Therefore the only way 
to get "1" to normally be an "int" but automatically convert to a 
"bool" without being inconsistent is to effectively introduce a 
new type for the literal "1" which has the desired conversions 
(the same way that zero has a special type in C/C++ which can 
convert to both an integer or a pointer).

The important thing is that this special type for "1" should 
never transfer to other things: the type of the literal should be 
fixed to a normal type at the point where it is used to prevent 
surprising the user (this is what C/C++ does).

At the moment "enum e = 1;" transfers the special properties of 
"1" to "e" and I think that's more than a little surprising.
Apr 26 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Apr 26 2013
next sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
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.
Apr 26 2013
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
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
Apr 26 2013
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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!
Apr 26 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 5:14 PM, H. S. Teoh wrote:
 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?
 		}
 		...
 	}
Such would require data flow analysis, which is beyond the scope of what the front end is designed to do. So, no, for the foreseeable future.
Apr 27 2013
prev sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Friday, 26 April 2013 at 21:34:44 UTC, Walter Bright wrote:
 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:
Then perhaps ban VRP on arguments if it affects overloading?
Apr 26 2013
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/26/2013 9:19 PM, Maxim Fomin wrote:
 Then perhaps ban VRP on arguments if it affects overloading?
That'll just make another group of people unhappy. It's like designing a house with a fixed footprint. You can make the kitchen larger and the bathroom smaller, or vice versa, but you can't make them both bigger.
Apr 27 2013
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 27, 2013 06:19:29 Maxim Fomin wrote:
 On Friday, 26 April 2013 at 21:34:44 UTC, Walter Bright wrote:
 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:
Then perhaps ban VRP on arguments if it affects overloading?
No. The problem really isn't with VRP. The problem is the fact that D is weakly typed with regards to bool. In virtually all cases, having VRP do it's job is exactly what we want. It's just that in this one, weird things happen because of the implicit conversion to bool which is of zero utility in this case, because if that's what you wanted, you'd just use a boolean literal rather than an integer one. I really think that allowing the implicit conversion to bool is truly helpful in only a small number of cases (e.g. arithmetic which wants to add 0 or 1 depending on the result of a boolean expression), and it clearly results in behavior that most people don't expect in quite a few instances. The fact that stuff like auto b = false / true; compiles is just downright bizarre. - Jonathan M Davis
Apr 27 2013
parent Paulo Pinto <pjmlp progtools.org> writes:
Am 28.04.2013 02:34, schrieb Jonathan M Davis:
 On Saturday, April 27, 2013 06:19:29 Maxim Fomin wrote:
 On Friday, 26 April 2013 at 21:34:44 UTC, Walter Bright wrote:
 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:
Then perhaps ban VRP on arguments if it affects overloading?
No. The problem really isn't with VRP. The problem is the fact that D is weakly typed with regards to bool. In virtually all cases, having VRP do it's job is exactly what we want. It's just that in this one, weird things happen because of the implicit conversion to bool which is of zero utility in this case, because if that's what you wanted, you'd just use a boolean literal rather than an integer one. I really think that allowing the implicit conversion to bool is truly helpful in only a small number of cases (e.g. arithmetic which wants to add 0 or 1 depending on the result of a boolean expression), and it clearly results in behavior that most people don't expect in quite a few instances. The fact that stuff like auto b = false / true; compiles is just downright bizarre. - Jonathan M Davis
Well, we need material to write "D the good parts" :)
Apr 27 2013