April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | 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
}
|
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | 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 |
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | 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).
|
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | 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.
|
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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!
|
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to jerro | 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.
|
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | 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 |
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | 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.
|
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | 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>
|
April 28, 2013 Re: 1 matches bool, 2 matches long | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | 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.
|
Copyright © 1999-2021 by the D Language Foundation