April 28, 2013
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?
April 28, 2013
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" :)
April 28, 2013
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


April 28, 2013
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


April 28, 2013
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.

April 28, 2013
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.
April 28, 2013
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.

April 28, 2013
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.
April 28, 2013
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 . . .
April 28, 2013
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