Re: Operator overloading, structs

2009-06-26 Thread Don

Leandro Lucarella wrote:

Don, el 10 de junio a las 03:50 me escribiste:

Leandro Lucarella wrote:

Don, el 10 de junio a las 02:02 me escribiste:

bearophile wrote:

Leandro Lucarella:

I think the more general solution is to allow multiple implicit cast
operators and simply provide implicit conversion to bool for the classes
you want to be able to do if (x) on.

No, it's not more general.

*it is* more general, that's exactly what you don't like about it =)

If you consider also introduces bugs as more general... I just call that wrong 
g.


No, I consider not specialized or limited to one class of things[1] as
more general. I'm not discussing if generality makes easy to introduce
bugs in this case, that is what you are implying =)


I'm implying that it does NOTHING other than introduce bugs.
If you want to be pedantic: it does not reduce the limitations on useful 
behaviour.




[1] Meaning taken from here http://wordnetweb.princeton.edu/perl/webwn?s=general
(I've choose the meaning that better fit what I was trying to say)


C++ libraries go to a fair bit of trouble to allow if(x) without
allowing x to be converted to bool.

I don't think is a *disaster*, but I agree that maybe the distintion can
be useful (I didn't though about that). 

It's very important. If you allow implicit conversion to bool, all kinds
of garbage will compile. You might as well abandon static typing.


Again, I think this is a little too drastic.


That makes me think, why not to

disable implicit cast from bool to int? It's even defined what the value
of int x = true; should be?

Yes. It's 1.


I guess there are plenty of cases where you
don't want that, but I can't think of anything now...

I can't think of any case where it's a good idea. (It's required in D1
because opEquals() stupidly returns int).


I don't think is *required*, you can do an explicit cast, but it wouldn't
be very nice indeed. BTW, wasn't that finally changed? Or it was a D2 only
change?


But that still leaves the problem:

bool b = x; // doesn't compile if x is a class, or an array, or an AA.
But it would compile if x is a struct with implicit conversion to bool.


I don't understand why that should not compile if the class/array/AA has
an implicit conversion to bool defined.


Of course, int to bool implicit cast should still be possible.

No. It isn't legal now! Only the special case of literals 0 and 1. Which is 
perfect.


So is:

int x;
// ...
if (x)
// ..

A special case? That's odd...


It's a special idiom, which you mention at the end of your post. It 
doesn't involve implicit conversion to bool. Thus avoiding bugs.



I think it makes perfect sense to allow implicit conversion from int to
bool. I don't think bool should be considered a numeric type to be
concerned about the precision loss (or there is another reason not to
allow that?).


The only time when you want to allow an implicit conversion to bool is
when you have some kind of smart bool struct which is supposed to be
a drop-in replacement for bool. It's quite distinct from
if(x) -- if(x!=0).

The strength of my proposal is that it would allow existing code to
just work without modification. You wouldn't have to think about it.
To argue against it, find a situation where it would be a problem.


I think implicit conversion to bool is a very common idiom to quickly ask
if something is not empty.


That is not correct. if(x) does NOT involve an implicit conversion to 
bool. That's the key issue.


Re: Operator overloading, structs

2009-06-22 Thread bearophile
bearophile:
 When the complex numbers are implemented by a struct in the standard library 
 (or as in the original case of BigInts), I may like to keep being able to 
 write:
 if (x) { ... }
 Where x is a Complex struct or BigInt struct that defines something like an 
 opBool.
 In both those situations you can write:
 if (x != 0) { ... }
 They just need to define opEquals(int).

It seems I was right, C# too defines something like it, true and false 
operators (I don't know why they have both of them; isn't one enough?):
http://www.java2s.com/Tutorial/CSharp/0160__Operator-Overload/truefalseoperatorforComplex.htm

There's a certain number of C# features I'd like to see in D (like nullable 
types that act as nan of floating point numbers, etc).

Bye,
bearophile


Re: Operator overloading, structs

2009-06-22 Thread Sam
bearophile Wrote:

 
 There's a certain number of C# features I'd like to see in D (like nullable 
 types that act as nan of floating point numbers, etc).
 
 Bye,
 bearophile
C#3 also provides the null coalescring operator (??):

Code snippet 1 in C#1:
Address address =user.getContactAddress;
if(address==null)
{
address=order.getShippingAddress;
if(address==null)
{
address=user.getBillingAddress;
}
}

Code snippet 2 in C#3 with ?? operator:

Address address=user.getContactAddress??
 user.getShippingAddress??
 user.getBillingAddress;


Regards,
Sam


Re: Operator overloading, structs

2009-06-10 Thread Leandro Lucarella
bearophile, el 10 de junio a las 08:23 me escribiste:
 Don:
  It's very important. If you allow implicit conversion to bool, all kinds 
  of garbage will compile. You might as well abandon static typing.
 
 Some half-backed ideas.
 opBool() can be called implicitly when it's required a truth value test, like 
 in if(x), while(x || y), etc.
 So this produces a type error:
 bool b = x;

I just can't understand why someone would not want this conversion to work
without a cast. Can anyone explain to me?

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)

All mail clients suck. This one just sucks less. -me, circa 1995


Re: Operator overloading, structs

2009-06-10 Thread Leandro Lucarella
Don, el 10 de junio a las 03:50 me escribiste:
 Leandro Lucarella wrote:
 Don, el 10 de junio a las 02:02 me escribiste:
 bearophile wrote:
 Leandro Lucarella:
 I think the more general solution is to allow multiple implicit cast
 operators and simply provide implicit conversion to bool for the classes
 you want to be able to do if (x) on.
 No, it's not more general.
 *it is* more general, that's exactly what you don't like about it =)
 
 If you consider also introduces bugs as more general... I just call that 
 wrong g.

No, I consider not specialized or limited to one class of things[1] as
more general. I'm not discussing if generality makes easy to introduce
bugs in this case, that is what you are implying =)

[1] Meaning taken from here http://wordnetweb.princeton.edu/perl/webwn?s=general
(I've choose the meaning that better fit what I was trying to say)

 C++ libraries go to a fair bit of trouble to allow if(x) without
 allowing x to be converted to bool.
 I don't think is a *disaster*, but I agree that maybe the distintion can
 be useful (I didn't though about that). 
 
 It's very important. If you allow implicit conversion to bool, all kinds
 of garbage will compile. You might as well abandon static typing.

Again, I think this is a little too drastic.

 That makes me think, why not to
 disable implicit cast from bool to int? It's even defined what the value
 of int x = true; should be?
 Yes. It's 1.
 
  I guess there are plenty of cases where you
 don't want that, but I can't think of anything now...
 
 I can't think of any case where it's a good idea. (It's required in D1
 because opEquals() stupidly returns int).

I don't think is *required*, you can do an explicit cast, but it wouldn't
be very nice indeed. BTW, wasn't that finally changed? Or it was a D2 only
change?

 But that still leaves the problem:
 
 bool b = x; // doesn't compile if x is a class, or an array, or an AA.
 But it would compile if x is a struct with implicit conversion to bool.

I don't understand why that should not compile if the class/array/AA has
an implicit conversion to bool defined.

 Of course, int to bool implicit cast should still be possible.
 
 No. It isn't legal now! Only the special case of literals 0 and 1. Which is 
 perfect.

So is:

int x;
// ...
if (x)
// ..

A special case? That's odd...

I think it makes perfect sense to allow implicit conversion from int to
bool. I don't think bool should be considered a numeric type to be
concerned about the precision loss (or there is another reason not to
allow that?).

 The only time when you want to allow an implicit conversion to bool is
 when you have some kind of smart bool struct which is supposed to be
 a drop-in replacement for bool. It's quite distinct from
 if(x) -- if(x!=0).
 
 The strength of my proposal is that it would allow existing code to
 just work without modification. You wouldn't have to think about it.
 To argue against it, find a situation where it would be a problem.

I think implicit conversion to bool is a very common idiom to quickly ask
if something is not empty. Most languages do that...

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)

De las generaciones venideras espero, nada más, que vengan.
-- Ricardo Vaporeso


Re: Operator overloading, structs

2009-06-09 Thread bearophile
Don:
 That is, if x is a struct, convert if(x) into if(x==0)
 and convert if(!x) into if(x!=0). Usual rules would then apply, so 
 any opEquals with a parameter which could be implicitly cast from 0 
 would work.
 That wouldn't allow smart-pointer structs to implement if (x) without 
 requiring them to allow comparisons with integers, so it might be 
 necessary to add a second step: try if(x==null) instead.

I don't like this solution, because it relies on a bit of invisible magic, and 
you too have seen it needs extensions because it's not general.
If you want to use if (x) where x doesn't represent a number but something else 
like a collection, they you have to add even more special cases like add a 
third step: if(x.length == 0) etc. So this is not a good solution.


 Alternatively, introduce a bool opNull() member function for structs.

A similar method (we can discuss its name, that must be related to its 
semantic(*)) requires no invisible magic, it's clean and easy to use and 
implement, and it works on all three cases we have shown. This is a better 
solution.


(*) I have suggested a name like bool opBool(), so if you perform a cast(bool)x 
this is the method that is called. But someone has said that in the case of 
if(x) that's not the method that is implicitly called... But it may be better 
to call it instead. So for me it's better to leave this to someone more expert 
than me.

Bye,
bearophile


Re: Operator overloading, structs

2009-06-09 Thread Leandro Lucarella
bearophile, el  9 de junio a las 08:19 me escribiste:
 Don:
  That is, if x is a struct, convert if(x) into if(x==0)
  and convert if(!x) into if(x!=0). Usual rules would then apply, so 
  any opEquals with a parameter which could be implicitly cast from 0 
  would work.
  That wouldn't allow smart-pointer structs to implement if (x) without 
  requiring them to allow comparisons with integers, so it might be 
  necessary to add a second step: try if(x==null) instead.
 
 I don't like this solution, because it relies on a bit of invisible
 magic, and you too have seen it needs extensions because it's not
 general.  If you want to use if (x) where x doesn't represent a number
 but something else like a collection, they you have to add even more
 special cases like add a third step: if(x.length == 0) etc. So this is
 not a good solution.

I think the more general solution is to allow multiple implicit cast
operators and simply provide implicit conversion to bool for the classes
you want to be able to do if (x) on.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)



Re: Operator overloading, structs

2009-06-09 Thread bearophile
Leandro Lucarella:
 I think the more general solution is to allow multiple implicit cast
 operators and simply provide implicit conversion to bool for the classes
 you want to be able to do if (x) on.

Yes, that's a more general solution, but I think Don thinks that solution is 
also less safe.
I don't have enough experience on this to be able to tell, but generally the 
less invisible magic there is, the more clear the programs are. So better to 
limit the magic the few places where it's very useful (and where people know 
very well it can be present).

Bye,
bearophile


Re: Operator overloading, structs

2009-06-09 Thread Don

bearophile wrote:

Leandro Lucarella:

I think the more general solution is to allow multiple implicit cast
operators and simply provide implicit conversion to bool for the classes
you want to be able to do if (x) on.


No, it's not more general. You do NOT want to allow conversion to bool. 
 The reason is that bool can itself be implicitly converted, eg this 
compiles:


   bool b = true;
   int y = b;

--
And that's a disaster:

struct Foo
{
  bool opImplicitCast() { return true; }
}

Foo x;
if (x) { ... }  // OK
int y = x;  // This would compile

C++ libraries go to a fair bit of trouble to allow if(x) without 
allowing x to be converted to bool.


Re: Operator overloading, structs

2009-06-09 Thread Leandro Lucarella
Don, el 10 de junio a las 02:02 me escribiste:
 bearophile wrote:
 Leandro Lucarella:
 I think the more general solution is to allow multiple implicit cast
 operators and simply provide implicit conversion to bool for the classes
 you want to be able to do if (x) on.
 
 No, it's not more general.

*it is* more general, that's exactly what you don't like about it =)

 You do NOT want to allow conversion to bool.  The reason is that bool
 can itself be implicitly converted, eg this compiles:
 
bool b = true;
int y = b;
 
 --
 And that's a disaster:
 
 struct Foo
 {
   bool opImplicitCast() { return true; }
 }
 
 Foo x;
 if (x) { ... }  // OK
 int y = x;  // This would compile
 
 C++ libraries go to a fair bit of trouble to allow if(x) without
 allowing x to be converted to bool.

I don't think is a *disaster*, but I agree that maybe the distintion can
be useful (I didn't though about that). That makes me think, why not to
disable implicit cast from bool to int? It's even defined what the value
of int x = true; should be? I guess there are plenty of cases where you
don't want that, but I can't think of anything now...

Of course, int to bool implicit cast should still be possible.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/

GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)

Le pedí que me enseñe a usar el mouse
Pero solo quiere hablarme del Bauhaus
Le pregunté si era chorra o rockera
Me dijo Gertrude Stein era re-tortillera
Me hizo mucho mal la cumbiera intelectual


Re: Operator overloading, structs

2009-06-09 Thread Don

Leandro Lucarella wrote:

Don, el 10 de junio a las 02:02 me escribiste:

bearophile wrote:

Leandro Lucarella:

I think the more general solution is to allow multiple implicit cast
operators and simply provide implicit conversion to bool for the classes
you want to be able to do if (x) on.

No, it's not more general.


*it is* more general, that's exactly what you don't like about it =)


If you consider also introduces bugs as more general... I just call 
that wrong g.





You do NOT want to allow conversion to bool.  The reason is that bool
can itself be implicitly converted, eg this compiles:

   bool b = true;
   int y = b;

--
And that's a disaster:

struct Foo
{
  bool opImplicitCast() { return true; }
}

Foo x;
if (x) { ... }  // OK
int y = x;  // This would compile

C++ libraries go to a fair bit of trouble to allow if(x) without
allowing x to be converted to bool.


I don't think is a *disaster*, but I agree that maybe the distintion can
be useful (I didn't though about that). 


It's very important. If you allow implicit conversion to bool, all kinds 
of garbage will compile. You might as well abandon static typing.


That makes me think, why not to

disable implicit cast from bool to int? It's even defined what the value
of int x = true; should be?

Yes. It's 1.

 I guess there are plenty of cases where you

don't want that, but I can't think of anything now...


I can't think of any case where it's a good idea. (It's required in D1 
because opEquals() stupidly returns int).

But that still leaves the problem:

bool b = x; // doesn't compile if x is a class, or an array, or an AA.
But it would compile if x is a struct with implicit conversion to bool.


Of course, int to bool implicit cast should still be possible.


No. It isn't legal now! Only the special case of literals 0 and 1. Which 
is perfect.


The only time when you want to allow an implicit conversion to bool is 
when you have some kind of smart bool struct which is supposed to be a 
drop-in replacement for bool. It's quite distinct from

if(x) -- if(x!=0).

The strength of my proposal is that it would allow existing code to 
just work without modification. You wouldn't have to think about it.

To argue against it, find a situation where it would be a problem.


Re: Operator overloading, structs

2009-06-08 Thread bearophile
Don:
 On second thoughts, y = x.toLong or y = to!(long)(x) is probably better. 
 Casts are evil, implicit casts even more so.

I have seen you have added opEquals(int) and the like, thank you.
But I don't see an efficient way to convert to int/long yet.

Bye,
bearophile


Re: Operator overloading, structs

2009-06-08 Thread Don

Denis Koroskin wrote:
On Thu, 04 Jun 2009 22:10:58 +0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org wrote:



Max Samukha wrote:

On Thu, 04 Jun 2009 10:41:31 -0500, Andrei Alexandrescu
seewebsiteforem...@erdani.org wrote:

You are mistakenly presupposing that if() takes a bool. In reality 
if() accepts a bool, an integral, a floating-point type, a pointer, 
an array, or a class reference.

 or delegate


I was sure I forgot something... and hash too. Anything that can be 
compared against 0 or null.


Andrei


Is it considered a good practice?

Technically, the following construct is not exactly portable:

float f = ..;
if (f) {
}

because C (nor D) standard doesn't guaranty that float(0) will be 
implemented as all bits set to 0 on target platform (although it 
currently holds true).


That _is_ guaranteed. Even on not-quite-conformant systems.
Actually, -0.0 is not implemented as all-bits-zero, yet this works:
void main(){
   float f = -0.0;
   if (f) assert(0);
}
There's no portability problem here.

To fix the original issue, we'd just need to allow something like:

struct S
{
   bool opEquals(int x) { return (x!=0); }
}

void main()
{
   S x;
   if (x) assert(0);
}

That is, if x is a struct, convert if(x) into if(x==0)
and convert if(!x) into if(x!=0). Usual rules would then apply, so 
any opEquals with a parameter which could be implicitly cast from 0 
would work.


That wouldn't allow smart-pointer structs to implement if (x) without 
requiring them to allow comparisons with integers, so it might be 
necessary to add a second step: try if(x==null) instead.


Alternatively, introduce a bool opNull() member function for structs.
Both solutions are easy to implement.


Re: Operator overloading, structs

2009-06-05 Thread Max Samukha
On Thu, 04 Jun 2009 13:10:58 -0500, Andrei Alexandrescu
seewebsiteforem...@erdani.org wrote:

Max Samukha wrote:
 On Thu, 04 Jun 2009 10:41:31 -0500, Andrei Alexandrescu
 seewebsiteforem...@erdani.org wrote:
 
 
 You are mistakenly presupposing that if() takes a bool. In reality if() 
 accepts a bool, an integral, a floating-point type, a pointer, an array, 
 or a class reference.
 
 or delegate

I was sure I forgot something... and hash too. Anything that can be 
compared against 0 or null.

Andrei
Yeah. If anybody doesn't know, it works like this:
IfStatement::semantic checks Expression::checkToBoolean, which for
delete, assignment etc issues an error and for other expressions calls
Type::checkBoolean, which for most types except arrays, class
references etc. calls isscalar().   


Re: Operator overloading, structs

2009-06-05 Thread Yigal Chripun

bearophile wrote:

Yigal Chripun:


what's more readable, my version or yours?


Mine, ihmo :-) Less things to remember. And the code is shorter and
less noisy. Java programmers seems to

ignore how much noisy is their code.

empty collections are false is easy. You don't have to write code
like:  string s;
if (s == null) ...
if (s == ) ...
if (s.length == 0) ...
if (s.length) ...
Or even:
if (s is null) ...
And few other variants I have seen in D code or snippets. Such things


Do confuse d newbies (see digitalmars.D.learn).

(If a collection is a class, and the object doesn't exists yet, and

the variable is just a null reference, then it's false anyway the
collection is empty still. Do you like this?).




is a bad pattern.


Why?



it is even more problematic with floats.


I think I have never had troubles from zero testing of

floats/double/reals in D.


If you want to try to convince other people (and I don't think D will


change on this) you have to start listing some downsides of the current
design, some real bugs it leads to, and so on.


Bye,
bearophile


for starters, null and empty are two distinct concepts and sometimes it 
is important to know the difference.

 if (s is null) ...
 if (s == ) ... // NOT same thing as above

also, with your version you need to remember _more_ things when reading 
code. I agree that the code is shorter but this is insignificant in this 
case.
Java code has nothing to do with this and this is NOT the reason why 
Java code can be noisy.


Re: Operator overloading, structs

2009-06-04 Thread Yigal Chripun

Andrei Alexandrescu wrote:

Yigal Chripun wrote:
your abstraction inversion example doesn't apply here. The problem I 
see is the narrowing implicit cast, i.e. int values behave like 
booleans. I have no problem with the reverse which is what your 
example is about.


An int does not convert to bool implicitly. An int can be tested with 
if, which is a different thing.


Andrei


that is an implicit cast.
what I'm saying is that:

 int a = .. ;
 if (a) { .. }

this should be a compiler error IMO.


Re: Operator overloading, structs

2009-06-04 Thread bearophile
Yigal Chripun:
 that is an implicit cast.
 what I'm saying is that:
 
   int a = .. ;
   if (a) { .. }
 
 this should be a compiler error IMO.

I think the opposite is good: that empty collections are false, so the 
following ones print X:

int[]  a;
if (!a) printf(X);
Set!(int) s;
if (!s) printf(X);
int[string] aa;
if (!aa) printf(X);

Bye,
bearophile


Re: Operator overloading, structs

2009-06-04 Thread Derek Parnell
On Thu, 04 Jun 2009 10:06:45 +0300, Yigal Chripun wrote:

 Andrei Alexandrescu wrote:
 Yigal Chripun wrote:
 your abstraction inversion example doesn't apply here. The problem I 
 see is the narrowing implicit cast, i.e. int values behave like 
 booleans. I have no problem with the reverse which is what your 
 example is about.
 
 An int does not convert to bool implicitly. An int can be tested with 
 if, which is a different thing.
 
 Andrei
 
 that is an implicit cast.
 what I'm saying is that:
 
   int a = .. ;
   if (a) { .. }
 
 this should be a compiler error IMO.

I'm not agreeing with you, Yigal.

I think that the idiom you described is not equivalent to 

   if (a == TRUE) { .. }

but really 

   if (a != 0) { .. }

when 'a' is an integer of any size or sign. 

This should *not* be a compiler error as it is a convenient shorthand for
some coders. Personally, I try not to code this idiom because I find it
misleading in terms of self documentation ... but then I'm against using
goto as well ;-)


-- 
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell


Re: Operator overloading, structs

2009-06-04 Thread Andrei Alexandrescu

Yigal Chripun wrote:

Andrei Alexandrescu wrote:

Yigal Chripun wrote:
your abstraction inversion example doesn't apply here. The problem I 
see is the narrowing implicit cast, i.e. int values behave like 
booleans. I have no problem with the reverse which is what your 
example is about.


An int does not convert to bool implicitly. An int can be tested with 
if, which is a different thing.


Andrei


that is an implicit cast.


No. An implicit cast is this:

int a;
bool b = a; // doesn't compile

or this:

void fun(bool);
fun(5); // doesn't compile

You are mistakenly presupposing that if() takes a bool. In reality if() 
accepts a bool, an integral, a floating-point type, a pointer, an array, 
or a class reference.



Andrei



Re: Operator overloading, structs

2009-06-04 Thread Max Samukha
On Thu, 04 Jun 2009 10:41:31 -0500, Andrei Alexandrescu
seewebsiteforem...@erdani.org wrote:


You are mistakenly presupposing that if() takes a bool. In reality if() 
accepts a bool, an integral, a floating-point type, a pointer, an array, 
or a class reference.

or delegate


Re: Operator overloading, structs

2009-06-04 Thread Andrei Alexandrescu

Max Samukha wrote:

On Thu, 04 Jun 2009 10:41:31 -0500, Andrei Alexandrescu
seewebsiteforem...@erdani.org wrote:


You are mistakenly presupposing that if() takes a bool. In reality if() 
accepts a bool, an integral, a floating-point type, a pointer, an array, 
or a class reference.


or delegate


I was sure I forgot something... and hash too. Anything that can be 
compared against 0 or null.


Andrei


Re: Operator overloading, structs

2009-06-04 Thread Denis Koroskin
On Thu, 04 Jun 2009 22:10:58 +0400, Andrei Alexandrescu  
seewebsiteforem...@erdani.org wrote:



Max Samukha wrote:

On Thu, 04 Jun 2009 10:41:31 -0500, Andrei Alexandrescu
seewebsiteforem...@erdani.org wrote:

You are mistakenly presupposing that if() takes a bool. In reality  
if() accepts a bool, an integral, a floating-point type, a pointer, an  
array, or a class reference.

 or delegate


I was sure I forgot something... and hash too. Anything that can be  
compared against 0 or null.


Andrei


Is it considered a good practice?

Technically, the following construct is not exactly portable:

float f = ..;
if (f) {
}

because C (nor D) standard doesn't guaranty that float(0) will be  
implemented as all bits set to 0 on target platform (although it  
currently holds true).


I believe it is better to use an epsilon, instead:

if (fabsf(f)  epsilon) {
}

unless you need to compare strictly against 0:

if (f == 0) {
}


Re: Operator overloading, structs

2009-06-04 Thread Yigal Chripun

Andrei Alexandrescu wrote:

Yigal Chripun wrote:

Andrei Alexandrescu wrote:

Yigal Chripun wrote:
your abstraction inversion example doesn't apply here. The problem I 
see is the narrowing implicit cast, i.e. int values behave like 
booleans. I have no problem with the reverse which is what your 
example is about.


An int does not convert to bool implicitly. An int can be tested with 
if, which is a different thing.


Andrei


that is an implicit cast.


No. An implicit cast is this:

int a;
bool b = a; // doesn't compile

or this:

void fun(bool);
fun(5); // doesn't compile

You are mistakenly presupposing that if() takes a bool. In reality if() 
accepts a bool, an integral, a floating-point type, a pointer, an array, 
or a class reference.



Andrei



I'm not debating terminology with you nor am I presupposing that if() 
currently takes a bool, I know it takes other types as well.
what I am saying is that if needs to be fixed such that it _will_ take 
only bool. the the C idiom of:


  int a = ...;
  if (a) {...}

is a bad pattern. it is even more problematic with floats.
it _should_ be written always as:
if (a == 0) { .. }

zero is not false. in fact zero can be very positive: zero errors, zero 
 cache misses, etc.


Re: Operator overloading, structs

2009-06-04 Thread Yigal Chripun

Derek Parnell wrote:

On Thu, 04 Jun 2009 10:06:45 +0300, Yigal Chripun wrote:


Andrei Alexandrescu wrote:

Yigal Chripun wrote:
your abstraction inversion example doesn't apply here. The problem I 
see is the narrowing implicit cast, i.e. int values behave like 
booleans. I have no problem with the reverse which is what your 
example is about.
An int does not convert to bool implicitly. An int can be tested with 
if, which is a different thing.


Andrei

that is an implicit cast.
what I'm saying is that:

  int a = .. ;
  if (a) { .. }

this should be a compiler error IMO.


I'm not agreeing with you, Yigal.

I think that the idiom you described is not equivalent to 


   if (a == TRUE) { .. }

but really 


   if (a != 0) { .. }

when 'a' is an integer of any size or sign. 


This should *not* be a compiler error as it is a convenient shorthand for
some coders. Personally, I try not to code this idiom because I find it
misleading in terms of self documentation ... but then I'm against using
goto as well ;-)




I don't see how we disagree since you say yourself that you try to avoid 
this idiom and find it misleading in terms of documentation. which I 
agree with.
yes, it does save a few key strokes but as I said before, that's a 
really bad optimization since code is read much more often than it's 
written and readability is much more important than saving a few key 
strokes.


I also agree about goto. there are very rare cases where it is useful 
but outside those goto is a bad bad thing to use.


Re: Operator overloading, structs

2009-06-04 Thread Yigal Chripun

bearophile wrote:

Yigal Chripun:

that is an implicit cast.
what I'm saying is that:

  int a = .. ;
  if (a) { .. }

this should be a compiler error IMO.


I think the opposite is good: that empty collections are false, so the 
following ones print X:

int[]  a;
if (!a) printf(X);
Set!(int) s;
if (!s) printf(X);
int[string] aa;
if (!aa) printf(X);

Bye,
bearophile


what's so bad about using a general collection.empty() API?
 int[]  a;
 if (!a.empty) printf(X);
 Set!(int) s;
 if (!s.empty) printf(X);
 int[string] aa;
 if (!aa.empty) printf(X);

what's more readable, my version or yours?


Re: Operator overloading, structs

2009-06-04 Thread Jarrett Billingsley
On Thu, Jun 4, 2009 at 2:20 PM, Denis Koroskin 2kor...@gmail.com wrote:

 because C (nor D) standard doesn't guaranty that float(0) will be
 implemented as all bits set to 0 on target platform (although it currently
 holds true).

Actually, D does.

http://www.digitalmars.com/d/1.0/abi.html

D requires floating-point types to be IEEE 754 compliant (though the
current wording of 'real' might confusingly allow for other
standards).


Re: Operator overloading, structs

2009-06-04 Thread BCS

Reply to Jarrett,


On Thu, Jun 4, 2009 at 2:20 PM, Denis Koroskin 2kor...@gmail.com
wrote:


because C (nor D) standard doesn't guaranty that float(0) will be
implemented as all bits set to 0 on target platform (although it
currently holds true).


Actually, D does.

http://www.digitalmars.com/d/1.0/abi.html

D requires floating-point types to be IEEE 754 compliant (though the
current wording of 'real' might confusingly allow for other
standards).



I /think/ that it doesn't require that FP types be IEEE 754 types, just that 
they match the semantics (possibly with more accuracy). If you can assume 
that any FPU will be designed to work with IEEE 754 (would that be valid 
now days?), then you can assume that real will differ only by size. The only 
case I think you might need to look out for is where FP is done in software 
and at that point, what would real be anyway?





Re: Operator overloading, structs

2009-06-04 Thread bearophile
Yigal Chripun:

 what's more readable, my version or yours?

Mine, ihmo :-) Less things to remember.
And the code is shorter and less noisy. Java programmers seems to ignore how 
much noisy is their code.
empty collections are false is easy. You don't have to write code like:
string s;
if (s == null) ...
if (s == ) ...
if (s.length == 0) ...
if (s.length) ...
Or even:
if (s is null) ...
And few other variants I have seen in D code or snippets. Such things Do 
confuse d newbies (see digitalmars.D.learn).
(If a collection is a class, and the object doesn't exists yet, and the 
variable is just a null reference, then it's false anywaythe collection is 
empty still. Do you like this?).


is a bad pattern.

Why?


it is even more problematic with floats.

I think I have never had troubles from zero testing of floats/double/reals in D.

If you want to try to convince other people (and I don't think D will change on 
this) you have to start listing some downsides of the current design, some real 
bugs it leads to, and so on.

Bye,
bearophile


Re: Operator overloading, structs

2009-06-04 Thread Robert Fraser

BCS wrote:
If you can 
assume that any FPU will be designed to work with IEEE 754 (would that 
be valid now days?)


Not at all!

IIRC, some of the PS2's CPUs don't implement NaN or Infinity (just check 
out the Advanced page of PCSX2, you can set how accurately the various 
PS2 CPUs FP operations are emulated on x86). Not sure if the PS2 is now 
days, but...


Also, this is kind of old, but it suggests GPUs have all sorts of 
different behavior: http://www.cs.unc.edu/~ibr/projects/paranoia/ ... 
When being used only for graphics, accuracy often isn't as important as 
speed, however with GPGPU, I wouldn't be surprised if newer GPUs were 
IEEE-compliant.


Re: Operator overloading, structs

2009-06-03 Thread Yigal Chripun

bearophile wrote:

Yigal Chripun:

any small positive epsilon is still greater than zero.


Worse is better.
An engineering system, as for example a computer language, is the result of lot 
of compromises. Better to keep yourself flexible.

Bye,
bearophile


no. Worse is better implies a trade-off - you sacrifice something like 
purity, cleanliness, etc to gain simplicity of implementation.
What I was trying to convey is that this does not apply here since there 
is no trade off to make - you get nothing by going with the worse option 
in this case.


Re: Operator overloading, structs

2009-06-03 Thread Yigal Chripun

dsimcha wrote:

== Quote from bearophile (bearophileh...@lycos.com)'s article

Yigal Chripun:

why not just use (i != 0) in both cases?
Yes, here it can be done (if Don has implemented opEquals(int y)), 
but you don't

need that once you have something like opBool.

conversion of ints to bools in C is IMO a hole in the type system
 due to the lack of a boolean type in C. All those narrowing 
implicit casts inherited from C are a bad idea IMO.
Walter was right, converting a generic integral to bool requires 
some time, that

in the middle of the the nested loop can slow down code a bit (5%, in
 a case of mine).
A standard opBool method allows you to tell when a collection is 
empty, like an
empty string, an empty range, an empty array, and so on. you can use 
it instead of somecollection.isEmpty().
Java as Pascal keep booleans and integers separated, this looks 
tidy and clean.

I love clean things, but in practice I don't think the current design
 of D (and C, Python, and several other languages) leads to a 
significant amount of bugs. It seems one of those situations where 
practical considerations win over purity.


For D and other close to the metal languages, IMHO the int-bool 
relationship should stay the way it is simply because that's the way 
it works on the bare metal (at least on x86, for example, 
instructions like jz).  I think this is a good rule of thumb in a 
close to the metal language, and even in the general case:  When in 
doubt, do the thing that gives the user the least obstructed view of 
how things really work at the next lower level.  This avoids lots 
of silly abstraction inversions (One of which is building a strong 
boolean type on top of an int).




close to the metal does not imply in any way you code with binary
op-codes or assembly concepts. all it means is that it does not force 
upon you costly abstractions and mechanisms like a VM. this does not 
apply to this discussion since a bool type doesn't require a VM and does 
not penalize performance in any way.


your abstraction inversion example doesn't apply here. The problem I see 
is the narrowing implicit cast, i.e. int values behave like booleans. I 
have no problem with the reverse which is what your example is about.


Re: Operator overloading, structs

2009-06-03 Thread Andrei Alexandrescu

Yigal Chripun wrote:
your abstraction inversion example doesn't apply here. The problem I see 
is the narrowing implicit cast, i.e. int values behave like booleans. I 
have no problem with the reverse which is what your example is about.


An int does not convert to bool implicitly. An int can be tested with 
if, which is a different thing.


Andrei


Re: Operator overloading, structs

2009-06-02 Thread Daniel Keep


Don wrote:
 ...
 
 On second thoughts, y = x.toLong or y = to!(long)(x) is probably better.
 Casts are evil, implicit casts even more so.

If you add a toLong or to_long member to BigInt, then to!(long)(x) will
work automatically.  Something similar applies to fromLong/from_long and
to!(BigInt)(cast(long)y).


Re: Operator overloading, structs

2009-06-02 Thread bearophile
Don:

 Still, I wonder if D could simply do something like defining that for classes:
 if (x)  is always transformed into  if ( x!=0 )
 if (!x) is always transformed into  if ( x==0 )

Explicit is better than implicit. For example I'd like to have a set collection 
that is false when empty. In such situation I can write just the following 
method, it seems simpler and semantically cleaner than alternatives:

bool opBool() { return this.length != 0; }


On second thoughts, y = x.toLong or y = to!(long)(x) is probably better. Casts 
are evil, implicit casts even more so.

I don't know. Using esplicit casts/methods may be safer. 

So with your current changes to BigInt, in the following program to replace the 
int i with a BigInt:

void main() {
int i = 1;
if (i)
i++;
auto a = [10, 20, 30, 40];
printf(%d\n, a[i]);
}

you need to change the code like this:

void main() {
BigInt i = 1;
if (i != 0)
i++;
auto a = [10, 20, 30, 40];
printf(%d\n, to!(long)a[i]);
}

The toBool will help avoid the change in the second line.

I'd like to change programs as little as possible when I change the type of a 
variable from int to BigInt. This has also the big advantage that I can write 
templated algorithms that work with both ints and BigInts with as few static 
if as possible (to manage BigInts in a special way, for example adding that 
to!(long) ). That's why in such situation an implicit casting is handy.

-

Such almost-transparent replacement of ints with BigInts can be done also if 
BigInts are fast to perform operations with small integers (like with integers 
in range -1073741824 .. 1073741824).

I have done few easy benchmarks (that I can show you if you want) and I have 
seen that when a bigint contains only ~30 bits of data or less a BigInt is much 
slower than an int. Some speed difference is inevitable, but to help such 
replacement I think it can be good if BigInts gain speed optimizations for 
small such numbers. (And when you use BigInts that contain 5000+ bits such 
optimizazions don't slow down BigInts significantly).

Possible idea: you can test if the number needs less than 31 bits, if so, you 
can compute the operation using just a long. If the result then can be stored 
back in about 31 bits, then you are done. This is slower than a simple 
operation among ints but it may be much faster than the same operations done 
with BigInts.

When numbers are so small the BigInt may also avoid all heap activity (Lisp 
languages do this using tags, they use a tagged pointer, that can be a small 
integer, avoiding any memory allocation when the number is small enough).

Bye,
bearophile


Re: Operator overloading, structs

2009-06-02 Thread Yigal Chripun

bearophile wrote:






So with your current changes to BigInt, in the following program to

replace the int i with a BigInt:


void main() {
int i = 1;
if (i)
i++;
auto a = [10, 20, 30, 40];
printf(%d\n, a[i]);
}

you need to change the code like this:

void main() {
BigInt i = 1;
if (i != 0)
i++;
auto a = [10, 20, 30, 40];
printf(%d\n, to!(long)a[i]);
}

The toBool will help avoid the change in the second line.

I'd like to change programs as little as possible when I change the
type of a variable from int to BigInt. This has also the big
advantage that I can write templated algorithms that work with both
ints and BigInts with as few static if as possible (to manage
BigInts in a special way, for example adding that to!(long) ). That's
why in such situation an implicit casting is handy.



why not just use (i != 0) in both cases? this should work with any 
numeric type (so it'll be used in generic code).


conversion of ints to bools in C is IMO a hole in the type system due to 
the lack of a boolean type in C. All those narrowing implicit casts 
inherited from C are a bad idea IMO.


the need to convert the bigInt to long in order to print it is a design 
error in printf() - the format string should specify the formatting of 
the variables not their types.





Re: Operator overloading, structs

2009-06-02 Thread bearophile
Yigal Chripun:

 why not just use (i != 0) in both cases?

Yes, here it can be done (if Don has implemented opEquals(int y)), but you 
don't need that once you have something like opBool.


 conversion of ints to bools in C is IMO a hole in the type system due to 
 the lack of a boolean type in C. All those narrowing implicit casts 
 inherited from C are a bad idea IMO.

Walter was right, converting a generic integral to bool requires some time, 
that in the middle of the the nested loop can slow down code a bit (5%, in a 
case of mine).
A standard opBool method allows you to tell when a collection is empty, like an 
empty string, an empty range, an empty array, and so on. you can use it instead 
of somecollection.isEmpty().
Java as Pascal keep booleans and integers separated, this looks tidy and clean. 
I love clean things, but in practice I don't think the current design of D (and 
C, Python, and several other languages) leads to a significant amount of bugs. 
It seems one of those situations where practical considerations win over purity.
There are other situations where I'd like to see fixed some implicit type 
conversions. C# shows a saner design in such regard. There are few things in C# 
that I'd like to see copied by D.


 the need to convert the bigInt to long in order to print it is a design 
 error in printf() - the format string should specify the formatting of 
 the variables not their types.

printf was invented lot of time ago, in galaxy far away, when needs and 
situations were different.
That code of mine is wrong, this is more correct, so here it's not printf fault:
printf(%d\n, a[to!(long)i]);
Because it's i the BigInt, not the contents of the a array.

Bye,
bearophile


Re: Operator overloading, structs

2009-06-02 Thread dsimcha
== Quote from bearophile (bearophileh...@lycos.com)'s article
 Yigal Chripun:
  why not just use (i != 0) in both cases?
 Yes, here it can be done (if Don has implemented opEquals(int y)), but you 
 don't
need that once you have something like opBool.
  conversion of ints to bools in C is IMO a hole in the type system due to
  the lack of a boolean type in C. All those narrowing implicit casts
  inherited from C are a bad idea IMO.
 Walter was right, converting a generic integral to bool requires some time, 
 that
in the middle of the the nested loop can slow down code a bit (5%, in a case of 
mine).
 A standard opBool method allows you to tell when a collection is empty, like 
 an
empty string, an empty range, an empty array, and so on. you can use it instead 
of
somecollection.isEmpty().
 Java as Pascal keep booleans and integers separated, this looks tidy and 
 clean.
I love clean things, but in practice I don't think the current design of D (and 
C,
Python, and several other languages) leads to a significant amount of bugs. It
seems one of those situations where practical considerations win over purity.

For D and other close to the metal languages, IMHO the int-bool relationship
should stay the way it is simply because that's the way it works on the bare 
metal
(at least on x86, for example, instructions like jz).  I think this is a good 
rule
of thumb in a close to the metal language, and even in the general case:  When 
in
doubt, do the thing that gives the user the least obstructed view of how things
really work at the next lower level.  This avoids lots of silly abstraction
inversions (One of which is building a strong boolean type on top of an int).



Re: Operator overloading, structs

2009-06-02 Thread Yigal Chripun

bearophile wrote:

Yigal Chripun:


why not just use (i != 0) in both cases?


Yes, here it can be done (if Don has implemented opEquals(int y)),
but you don't need that once you have something like opBool.



conversion of ints to bools in C is IMO a hole in the type system
due to the lack of a boolean type in C. All those narrowing
implicit casts inherited from C are a bad idea IMO.


Walter was right, converting a generic integral to bool requires some
time, that in the middle of the the nested loop can slow down code a
bit (5%, in a case of mine). A standard opBool method allows you to
tell when a collection is empty, like an empty string, an empty
range, an empty array, and so on. you can use it instead of
somecollection.isEmpty(). Java as Pascal keep booleans and integers
separated, this looks tidy and clean. I love clean things, but in
practice I don't think the current design of D (and C, Python, and
several other languages) leads to a significant amount of bugs. It
seems one of those situations where practical considerations win over
purity. There are other situations where I'd like to see fixed some
implicit type conversions. C# shows a saner design in such regard.
There are few things in C# that I'd like to see copied by D.

if I understand you correctly, you claim that the C behavior is just 
more practical and/or useful than the Pascal approach. this is where we 
differ. The _only_ practical benefit I see is that it saves you two 
characters to type. on the other hand you get less readable code which 
can potentially be buggy.
it's not important that the chance to get a bug here for an experienced 
C programmer (or a Python one) is slim since the comparison is against 
absolute zero chance of bugs with the pure approach. any small positive 
epsilon is still greater than zero.





the need to convert the bigInt to long in order to print it is a
design error in printf() - the format string should specify the
formatting of the variables not their types.


printf was invented lot of time ago, in galaxy far away, when needs
and situations were different. That code of mine is wrong, this is
more correct, so here it's not printf fault: 
printf(%d\n, a[to!(long)i]); 

 Because it's i the BigInt, not the contents of the

a array.

Bye, bearophile


Re: Operator overloading, structs

2009-06-02 Thread bearophile
Yigal Chripun:
any small positive epsilon is still greater than zero.

Worse is better.
An engineering system, as for example a computer language, is the result of lot 
of compromises. Better to keep yourself flexible.

Bye,
bearophile


Re: Operator overloading, structs

2009-06-01 Thread Don

bearophile wrote:

This post is mostly about D2 operator overloading in general, but I also talk 
about problems in the API of Tango BigInts.

A small program that use multiprecision integers of Tango:


import tango.stdc.stdio: printf;
import tango.math.BigInt: bint = BigInt;

void main() {
bint i = 1; // #1
if (i) // #2
i++;
auto a = [10, 20, 30, 40];
printf(%d\n, a[i]); // #3
}


If you replace BigInt with int that program works.
With bigInteger it doesn't work, because I think:
- In #1 it doesn't call static opCall.
Works for me with int. I've fixed BigInt so that it now works with long 
as well.



- In #2 D doesn't have a standard method that returns true/false. In Python2.6 
such method is named __nonzero__ and in python3 it's named __bool__.
- In #3 there's no implicit cast to int.




I think that improving such D2 operator overloading is very good, it allows to 
use BigInts, SafeInts, Complex, etc, in a quite more transparent way, allowing 
very similar code to work with native and user defined types.

---

Regarding specifically BigInt:

D1 has opCast, but here I think not even a[cast(long)i] works, because BigInt 
doesn't define it yet. When a big int can't be converted to long, it can throw 
an exception.


Yes, that's not a bad idea.


Until a more efficient solution is found, I think BigInts must have a toString 
too. In most situations you don't print such numbers, you do lot of 
computations with them and then you finally print some of them. So often the 
time spent printing them is not much).


Not toString(), though. You MUST be able to specify if you want leading 
zeros, and if you want hex or decimal. I just (a) haven't got around to 
it; and (b) haven't been sure about the interface should be.


But I hate toString() so much, I'm _never_ going to support it. It's an 
OMDB (over my dead body). Sorry.



I think BigInt also may enjoy a lot methods like: int opEquals(int y), etc.

Ouch! That's a simple omission.
Fixed in Tango SVN 4717.


Re: Operator overloading, structs

2009-06-01 Thread bearophile
 - In #2 D doesn't have a standard method that returns true/false. In 
 Python2.6 such method is named __nonzero__ and in python3 it's named 
 __bool__.

No one has commented about that, but I think that having a way to overload 
cast(bool)foo is important. I use it in Python and I have shown why and how it 
can be used in D too. It's an easy thing to do and I think it's safe.

Don:

  D1 has opCast, but here I think not even a[cast(long)i] works, because 
  BigInt doesn't define it yet. When a big int can't be converted to long, it 
  can throw an exception.
 
 Yes, that's not a bad idea.

But eventually an implicit cast will be better (even if a bit less safe) in D2.


 Not toString(), though. You MUST be able to specify if you want leading 
 zeros, and if you want hex or decimal.

toString() is for the default case, when you just want the decimal number with 
no leading zeros. Then you can add other methods to output hex and all you want.
(In what situations do you want to print leading zeros of a big multiprecision 
integral value? I have never faced such need so far).


 But I hate toString() so much, I'm _never_ going to support it. It's an 
 OMDB (over my dead body). Sorry.

I have patched a copy of the bigint module to add the toString method. I'll 
keep using such patch for my programs. I want you well alive and happy too.


 Fixed in Tango SVN 4717.

Thank you.

Bye,
bearophile


Re: Operator overloading, structs

2009-06-01 Thread Don

bearophile wrote:

- In #2 D doesn't have a standard method that returns true/false. In Python2.6 such 
method is named __nonzero__ and in python3 it's named __bool__.


No one has commented about that, but I think that having a way to overload 
cast(bool)foo is important. I use it in Python and I have shown why and how it 
can be used in D too. It's an easy thing to do and I think it's safe.


It's definitely required for completeness. In C++ there's a hack to do 
it safely (you return a pointer to a private member class).
Still, I wonder if D could simply do something like defining that for 
classes:

if (x)  is always transformed into  if ( x!=0 )
if (!x) is always transformed into  if ( x==0 )



Don:


D1 has opCast, but here I think not even a[cast(long)i] works, because BigInt 
doesn't define it yet. When a big int can't be converted to long, it can throw 
an exception.

Yes, that's not a bad idea.


But eventually an implicit cast will be better (even if a bit less safe) in D2.


On second thoughts, y = x.toLong or y = to!(long)(x) is probably better. 
Casts are evil, implicit casts even more so.




Not toString(), though. You MUST be able to specify if you want leading 
zeros, and if you want hex or decimal.


toString() is for the default case, when you just want the decimal number with 
no leading zeros. Then you can add other methods to output hex and all you want.
(In what situations do you want to print leading zeros of a big multiprecision 
integral value? I have never faced such need so far).


BigFloat, for example.