December 07, 2009
bearophile wrote:
> Walter Bright:
> 
>> Think of it like the "bool" operator overload. bool gives a direct
>> way for user defined times to be tested for if statements, etc.
>> Similarly, U+ gives a direct way for user defined types to be
>> converted to their most desired arithmetic type.
> 
> I'd like opBool in D, for example to implement multiprecision numbers
> that can be used as integers in: if (somenumber) {...

Unfortunately experience with C++ has shown that things look simpler than they are. If opBool is an implicit conversion to bool, then all sorts of weird expressions are allowed. That's why conversion to bool is flat out unrecommended in C++. Instead, various libraries found alternate ways to allow testing with if without compromising things too much. Loki uses conversion to an opaque pointer type. Boost uses conversion to a pointer to member. The standard itself uses, I think, conversion of iostreams to void*.

In my draft spec of operators I have the test:

a ? <expr1> : <expr2>

where a is of user-defined type, rewritten as

!!a ? <expr1> : <expr2>

and the test:

if (a) <stmt>

rewritten as

if (!!a) <stmt>

This leads to perfect correspondence with the behavior of arrays, pointers, class references, and integrals: you can't convert any of those to bool but you can test them with if or the ternary operator. Rewriting to !!a achieves exactly the same thing.

So user-defined types may define ! to return bool with the usual semantics, and the compiler nicely takes care of the rest.


Andrei
December 07, 2009
KennyTM~ wrote:
> On Dec 7, 09 05:12, Andrei Alexandrescu wrote:
>> I am completely underwhelmed by 1-6 and have strong arguments against
>> each, but "frankly, my dear" I have bigger problems than that. I have
>> exactly zero valid reasons I could mention in TDPL, and that's my litmus
>> test. I find the operator utterly useless. If '+' stays in, then call it
>> horsetrading but the occasionally useful '^^=' must also be in.
>>
>> Andrei
> 
> There would be zero reason to explain 1.0 vs 1.00, 1.0e2 vs 1.0e+2, and 0xabc vs 0xABC vs 0Xabc vs 0XABC too.
> 
> And I thought there isn't ^^= yet just because Don's patch was only a proof-of-concept thing. (Currently 3*4^^2 doesn't event produce the expected result.) ^^= will be in, but that's irrelevant.

Not so. My patch included ^^=, but Walter stripped it out because he wasn't convinced there were enough use cases for it.
December 07, 2009
Andrei Alexandrescu wrote:
> bearophile wrote:
>> Walter Bright:
>>
>>> Think of it like the "bool" operator overload. bool gives a direct
>>> way for user defined times to be tested for if statements, etc.
>>> Similarly, U+ gives a direct way for user defined types to be
>>> converted to their most desired arithmetic type.
>>
>> I'd like opBool in D, for example to implement multiprecision numbers
>> that can be used as integers in: if (somenumber) {...
> 
> Unfortunately experience with C++ has shown that things look simpler than they are. If opBool is an implicit conversion to bool, then all sorts of weird expressions are allowed. That's why conversion to bool is flat out unrecommended in C++. Instead, various libraries found alternate ways to allow testing with if without compromising things too much. Loki uses conversion to an opaque pointer type. Boost uses conversion to a pointer to member. The standard itself uses, I think, conversion of iostreams to void*.
> 
> In my draft spec of operators I have the test:
> 
> a ? <expr1> : <expr2>
> 
> where a is of user-defined type, rewritten as
> 
> !!a ? <expr1> : <expr2>
> 
> and the test:
> 
> if (a) <stmt>
> 
> rewritten as
> 
> if (!!a) <stmt>
> 
> This leads to perfect correspondence with the behavior of arrays, pointers, class references, and integrals: you can't convert any of those to bool but you can test them with if or the ternary operator. Rewriting to !!a achieves exactly the same thing.
> 
> So user-defined types may define ! to return bool with the usual semantics, and the compiler nicely takes care of the rest.

That's great. Simple and effective.
December 07, 2009
Andrei Alexandrescu wrote:
> Walter Bright wrote:
>> Andrei Alexandrescu wrote:
>>> Walter Bright wrote:
>>>> Andrei Alexandrescu wrote:
>>>>> Is there any good use of unary +? As an aside, Perl programs do use it occasionally for syntactic disambiguation :o).
>>>>
>>>> An internet search reveals:
>>>>
>>>> 1. symmetry
>>>>
>>>> 2. compatibility with C and many other languages that use it
>>>>
>>>> 3. used with operator overloading to convert a user defined type to its preferred arithmetic representation (a cast can't know what the 'preferred' type is)
>>>>
>>>> 4. to create DSL languages, like Spirit, as Kenny points out
>>>>
>>>> 5. to coerce default integral promotion rules (again, cast(int) won't always produce the same result)
>>>>
>>>> 6. to visually emphasize that a literal is positive
>>>>
>>>> I say leave it in.
>>>
>>> I am completely underwhelmed by 1-6 and have strong arguments against each, but "frankly, my dear" I have bigger problems than that. I have exactly zero valid reasons I could mention in TDPL, and that's my litmus test. I find the operator utterly useless. If '+' stays in, then call it horsetrading but the occasionally useful '^^=' must also be in.
>>
>> Think of it like the "bool" operator overload. bool gives a direct way for user defined times to be tested for if statements, etc.
> 
> If I think of it that way, that doesn't look too good. The bool operator overload has been an unqualified and admitted failure for C++. The hacks used to avoid that failure are very ingenious; none was within the realm of what the language had planned or intended.
> 
>> Similarly, U+ gives a direct way for user defined types to be converted to their most desired arithmetic type.
> 
> Code that uses +a to convert a to another type? I'd consider that worse than a hack and worse than incompetent - it's downright malicious.
> 
> Andrei

And if Andrei has never heard of it, we can be pretty sure that very few programmmers would understand code that uses it.

It's really looking as though U+ is only for literals and for operator abuse.
December 07, 2009
Don wrote:
> Not so. My patch included ^^=, but Walter stripped it out because he wasn't convinced there were enough use cases for it.

Andrei's definitely in your camp on that one <g>.
December 07, 2009
Andrei Alexandrescu wrote:
> bearophile wrote:
>> Walter Bright:
>>
>>> Think of it like the "bool" operator overload. bool gives a direct way for user defined times to be tested for if statements, etc. Similarly, U+ gives a direct way for user defined types to be converted to their most desired arithmetic type.
>>
>> I'd like opBool in D, for example to implement multiprecision numbers that can be used as integers in: if (somenumber) {...
> 
> Unfortunately experience with C++ has shown that things look simpler than they are. If opBool is an implicit conversion to bool, then all sorts of weird expressions are allowed. That's why conversion to bool is flat out unrecommended in C++. Instead, various libraries found alternate ways to allow testing with if without compromising things too much. Loki uses conversion to an opaque pointer type. Boost uses conversion to a pointer to member. The standard itself uses, I think, conversion of iostreams to void*.

Isn't one of the key problems that bool conversion introduces is the follow on conversion to integral types?  If implicit bool -> integral conversion wasn't allowed, T -> bool conversion would be less problematic, no?
December 07, 2009
Brad Roberts wrote:
> Andrei Alexandrescu wrote:
>> bearophile wrote:
>>> Walter Bright:
>>>
>>>> Think of it like the "bool" operator overload. bool gives a direct
>>>> way for user defined times to be tested for if statements, etc.
>>>> Similarly, U+ gives a direct way for user defined types to be
>>>> converted to their most desired arithmetic type.
>>> I'd like opBool in D, for example to implement multiprecision numbers
>>> that can be used as integers in: if (somenumber) {...
>> Unfortunately experience with C++ has shown that things look simpler
>> than they are. If opBool is an implicit conversion to bool, then all
>> sorts of weird expressions are allowed. That's why conversion to bool is
>> flat out unrecommended in C++. Instead, various libraries found
>> alternate ways to allow testing with if without compromising things too
>> much. Loki uses conversion to an opaque pointer type. Boost uses
>> conversion to a pointer to member. The standard itself uses, I think,
>> conversion of iostreams to void*.
> 
> Isn't one of the key problems that bool conversion introduces is the follow on
> conversion to integral types?  If implicit bool -> integral conversion wasn't
> allowed, T -> bool conversion would be less problematic, no?

That is correct, and "less problematic" is exactly how I'd put it. There's a problem left. Assuming bool -> numeric conversion is impossible, there's still a problem. First, consider a class, array, pointer, or number x. This compiles:

if (x) stmt

This also compiles:

x ? expr1 : expr2

But this doesn't compile:

bool b = x;

Now consider we design tests to use opBool that effects implicit conversion to bool. Then, for a user-defined type x, all of the three samples above compile. Which means we have introduced a gratuitous incompatibility between user-defined and built-in types.

Then consider another problem: a type that allows if (x) also wants to allow if (!x). It's the natural thing to want. Then we need to define opBool and opUnary!"!" to work in concert, redundantly. Bleh.

I'm not sure how big problems these are. I think they are threatening enough that style manuals and coding standards mention both.

Using double negation !!x throughout, there are only advantages and no disadvantage. I hit that design with Pacquiao punches over the past week or so, and couldn't find any shortcoming. It's consistent across positive and negated uses, easy to understand, easy to define, consistent with built-in types, and Walter likes it.


Andrei
December 07, 2009
Andrei Alexandrescu wrote:

> Brad Roberts wrote:
>> Andrei Alexandrescu wrote:
>>> bearophile wrote:
>>>> Walter Bright:
>>>>
>>>>> Think of it like the "bool" operator overload. bool gives a direct way for user defined times to be tested for if statements, etc. Similarly, U+ gives a direct way for user defined types to be converted to their most desired arithmetic type.
>>>> I'd like opBool in D, for example to implement multiprecision numbers that can be used as integers in: if (somenumber) {...
>>> Unfortunately experience with C++ has shown that things look simpler than they are. If opBool is an implicit conversion to bool, then all sorts of weird expressions are allowed. That's why conversion to bool is flat out unrecommended in C++. Instead, various libraries found alternate ways to allow testing with if without compromising things too much. Loki uses conversion to an opaque pointer type. Boost uses conversion to a pointer to member. The standard itself uses, I think, conversion of iostreams to void*.
>> 
>> Isn't one of the key problems that bool conversion introduces is the
>> follow on
>> conversion to integral types?  If implicit bool -> integral conversion
>> wasn't allowed, T -> bool conversion would be less problematic, no?
> 
> That is correct, and "less problematic" is exactly how I'd put it. There's a problem left. Assuming bool -> numeric conversion is impossible, there's still a problem. First, consider a class, array, pointer, or number x. This compiles:
> 
> if (x) stmt
> 
> This also compiles:
> 
> x ? expr1 : expr2
> 
> But this doesn't compile:
> 
> bool b = x;
> 
> Now consider we design tests to use opBool that effects implicit conversion to bool. Then, for a user-defined type x, all of the three samples above compile. Which means we have introduced a gratuitous incompatibility between user-defined and built-in types.
> 
> Then consider another problem: a type that allows if (x) also wants to
> allow if (!x). It's the natural thing to want. Then we need to define
> opBool and opUnary!"!" to work in concert, redundantly. Bleh.
> 
> I'm not sure how big problems these are. I think they are threatening enough that style manuals and coding standards mention both.
> 
> Using double negation !!x throughout, there are only advantages and no disadvantage. I hit that design with Pacquiao punches over the past week or so, and couldn't find any shortcoming. It's consistent across positive and negated uses, easy to understand, easy to define, consistent with built-in types, and Walter likes it.
> 
> 
> Andrei

Couldn't we solv that by instead of introducing opBool, introduce opTrue. Which is defined as yielding a type testable for truth and is only invoked in the same situations that class references are used as thruth values? To me this looks like a simple solution.
December 07, 2009
On Mon, 07 Dec 2009 10:36:16 +0300, Johan Granberg <lijat.meREM@ovegmail.com> wrote:

> Andrei Alexandrescu wrote:
>
>> Brad Roberts wrote:
>>> Andrei Alexandrescu wrote:
>>>> bearophile wrote:
>>>>> Walter Bright:
>>>>>
>>>>>> Think of it like the "bool" operator overload. bool gives a direct
>>>>>> way for user defined times to be tested for if statements, etc.
>>>>>> Similarly, U+ gives a direct way for user defined types to be
>>>>>> converted to their most desired arithmetic type.
>>>>> I'd like opBool in D, for example to implement multiprecision numbers
>>>>> that can be used as integers in: if (somenumber) {...
>>>> Unfortunately experience with C++ has shown that things look simpler
>>>> than they are. If opBool is an implicit conversion to bool, then all
>>>> sorts of weird expressions are allowed. That's why conversion to bool is
>>>> flat out unrecommended in C++. Instead, various libraries found
>>>> alternate ways to allow testing with if without compromising things too
>>>> much. Loki uses conversion to an opaque pointer type. Boost uses
>>>> conversion to a pointer to member. The standard itself uses, I think,
>>>> conversion of iostreams to void*.
>>>
>>> Isn't one of the key problems that bool conversion introduces is the
>>> follow on
>>> conversion to integral types?  If implicit bool -> integral conversion
>>> wasn't allowed, T -> bool conversion would be less problematic, no?
>>
>> That is correct, and "less problematic" is exactly how I'd put it.
>> There's a problem left. Assuming bool -> numeric conversion is
>> impossible, there's still a problem. First, consider a class, array,
>> pointer, or number x. This compiles:
>>
>> if (x) stmt
>>
>> This also compiles:
>>
>> x ? expr1 : expr2
>>
>> But this doesn't compile:
>>
>> bool b = x;
>>
>> Now consider we design tests to use opBool that effects implicit
>> conversion to bool. Then, for a user-defined type x, all of the three
>> samples above compile. Which means we have introduced a gratuitous
>> incompatibility between user-defined and built-in types.
>>
>> Then consider another problem: a type that allows if (x) also wants to
>> allow if (!x). It's the natural thing to want. Then we need to define
>> opBool and opUnary!"!" to work in concert, redundantly. Bleh.
>>
>> I'm not sure how big problems these are. I think they are threatening
>> enough that style manuals and coding standards mention both.
>>
>> Using double negation !!x throughout, there are only advantages and no
>> disadvantage. I hit that design with Pacquiao punches over the past week
>> or so, and couldn't find any shortcoming. It's consistent across
>> positive and negated uses, easy to understand, easy to define,
>> consistent with built-in types, and Walter likes it.
>>
>>
>> Andrei
>
> Couldn't we solv that by instead of introducing opBool, introduce opTrue.
> Which is defined as yielding a type testable for truth and is only invoked
> in the same situations that class references are used as thruth values? To
> me this looks like a simple solution.

OpTrue also implies opFalse, which is redundant.
December 07, 2009
On Dec 7, 09 13:11, Don wrote:
> KennyTM~ wrote:
>> On Dec 7, 09 05:12, Andrei Alexandrescu wrote:
>>> I am completely underwhelmed by 1-6 and have strong arguments against
>>> each, but "frankly, my dear" I have bigger problems than that. I have
>>> exactly zero valid reasons I could mention in TDPL, and that's my litmus
>>> test. I find the operator utterly useless. If '+' stays in, then call it
>>> horsetrading but the occasionally useful '^^=' must also be in.
>>>
>>> Andrei
>>
>> There would be zero reason to explain 1.0 vs 1.00, 1.0e2 vs 1.0e+2,
>> and 0xabc vs 0xABC vs 0Xabc vs 0XABC too.
>>
>> And I thought there isn't ^^= yet just because Don's patch was only a
>> proof-of-concept thing. (Currently 3*4^^2 doesn't event produce the
>> expected result.) ^^= will be in, but that's irrelevant.
>
> Not so. My patch included ^^=, but Walter stripped it out because he
> wasn't convinced there were enough use cases for it.

Ah, I see.