www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Container Contravariance was Re: [typing] Type-erasure re generics

reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Jesse Phillips Wrote:

 I will first quote Wikipedia about C#[1]:
 
 "For example, in C# 3.0 generic parameters did not support co or
contravariance; List<A> was not equivalent to List<TypeDerivedFromTypeA> as one
might intuit; however, this is now supported in C# 4.0, though standard arrays
have always supported covariance & contravariance since .NET was introduced."
 
 Then I will show an example that does compile[2]:
 
 void main() {
     A[] = [new B(), new A()];
 }
 
 1. http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
 2. http://ideone.com/ZzDTs

Actually my example code should have been this[1]: class A {} class B:A {} void main() { A[] a = new B[6]; } 1. http://ideone.com/Q59iD
Sep 29 2010
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, September 29, 2010 11:20:11 Jesse Phillips wrote:
 Jesse Phillips Wrote:
 I will first quote Wikipedia about C#[1]:
 
 "For example, in C# 3.0 generic parameters did not support co or
 contravariance; List<A> was not equivalent to List<TypeDerivedFromTypeA>
 as one might intuit; however, this is now supported in C# 4.0, though
 standard arrays have always supported covariance & contravariance since
 .NET was introduced."
 
 Then I will show an example that does compile[2]:
 
 void main() {
 
     A[] = [new B(), new A()];
 
 }
 
 1.
 http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_sci
 ence) 2. http://ideone.com/ZzDTs

Actually my example code should have been this[1]: class A {} class B:A {} void main() { A[] a = new B[6]; } 1. http://ideone.com/Q59iD

Pelle's point still stands. a[0] = new A(); would be legal code if you could assign a B[] to an A[], and since an A isn't necessarily a B, that doesn't work at all. If the underlying type were actually A[], then it would be fine to use varying types derived from A, but since the underlying type would actually be B[], it would break B[] to put anything in it which wasn't a B or a type derived from B. Now, const A[] might work, since then you couldn't assign any of its values and any B in a B[] is obviously an A. So, I could see passing B[] to function that took a const A[] as working (though maybe there's something that I'm missing that would make that not work), but you can't assign a B[] to a mutable A[] or your going to be able to put the wrong type in the underlying B[]. - Jonathan M Davis
Sep 29 2010
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Jonathan M Davis Wrote:

 Pelle's point still stands.
 
 a[0] = new A();
 
 would be legal code if you could assign a B[] to an A[], and since an A isn't 
 necessarily a B, that doesn't work at all. If the underlying type were
actually 
 A[], then it would be fine to use varying types derived from A, but since the 
 underlying type would actually be B[], it would break B[] to put anything in
it 
 which wasn't a B or a type derived from B.

Ok, then let us actually test that and show it is valid[1]: class A {} class B:A {} void main() { A[] a = new B[6]; a[0] = new A(); } 1. http://ideone.com/5sUZt I have shown that what I am talking about is valid for Arrays (a container) but not templates. The issues of actually implementing it is not related to what I was replying to. I introduced it as a benefit to forgetting type information in "generics." I was then told "Having a container of one type should not be castable to a container of another type." So I am pointing out we need to remove this feature from arrays right now!
Sep 29 2010
parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Jonathan M Davis Wrote:

 Ok, then let us actually test that and show it is valid[1]:
 
 class A {}
 class B:A {}
 
 void main() {
     A[] a = new B[6];
     a[0] = new A();
 }
 
 1. http://ideone.com/5sUZt
 
 I have shown that what I am talking about is valid for Arrays (a container)
 but not templates. The issues of actually implementing it is not related
 to what I was replying to. I introduced it as a benefit to forgetting type
 information in "generics." I was then told "Having a container of one type
 should not be castable to a container of another type." So I am pointing
 out we need to remove this feature from arrays right now!

In Java, you can't use generics with arrays, so it's not an issue. But if the D code you give here compiles, then that's a bug and needs to be reported. - Jonathan M Davis

Java you will see that it has no issue converting the container, but throws an exception if inserting the wrong type: http://ideone.com/EZRvn Ok, I see the point: class A {} class B:A { void fly() {} } void main() { B[] b = new B[6]; A[] a = b; a[0] = new A(); b[0].fly(); } http://ideone.com/rLiVL Which is why others were saying you could have B converted to a const container of A as this conversion is good for passing a container of B to a function that takes a container of A.
Sep 29 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, September 29, 2010 13:37:49 Jesse Phillips wrote:
 Jonathan M Davis Wrote:
 Pelle's point still stands.
 
 a[0] = new A();
 
 would be legal code if you could assign a B[] to an A[], and since an A
 isn't necessarily a B, that doesn't work at all. If the underlying type
 were actually A[], then it would be fine to use varying types derived
 from A, but since the underlying type would actually be B[], it would
 break B[] to put anything in it which wasn't a B or a type derived from
 B.

Ok, then let us actually test that and show it is valid[1]: class A {} class B:A {} void main() { A[] a = new B[6]; a[0] = new A(); } 1. http://ideone.com/5sUZt I have shown that what I am talking about is valid for Arrays (a container) but not templates. The issues of actually implementing it is not related to what I was replying to. I introduced it as a benefit to forgetting type information in "generics." I was then told "Having a container of one type should not be castable to a container of another type." So I am pointing out we need to remove this feature from arrays right now!

In Java, you can't use generics with arrays, so it's not an issue. But if the D code you give here compiles, then that's a bug and needs to be reported. - Jonathan M Davis
Sep 29 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, September 29, 2010 16:19:48 Jesse Phillips wrote:
 Jonathan M Davis Wrote:
 Ok, then let us actually test that and show it is valid[1]:
 
 class A {}
 class B:A {}
 
 void main() {
 
     A[] a = new B[6];
     a[0] = new A();
 
 }
 
 1. http://ideone.com/5sUZt
 
 I have shown that what I am talking about is valid for Arrays (a
 container) but not templates. The issues of actually implementing it
 is not related to what I was replying to. I introduced it as a benefit
 to forgetting type information in "generics." I was then told "Having
 a container of one type should not be castable to a container of
 another type." So I am pointing out we need to remove this feature
 from arrays right now!

In Java, you can't use generics with arrays, so it's not an issue. But if the D code you give here compiles, then that's a bug and needs to be reported. - Jonathan M Davis

Java you will see that it has no issue converting the container, but throws an exception if inserting the wrong type: http://ideone.com/EZRvn

Ah, okay. That's true: the fact that you can't have generic arrays doesn't stop you from pointing an array reference of one type at another with a derived type. I would have thought that it would disallow that though. Well, Java is much bigger on runtime checks than compile-time checks.
 Ok, I see the point:
 
 class A {}
 class B:A { void fly() {} }
 
 void main() {
     B[] b = new B[6];
     A[] a = b;
     a[0] = new A();
 
     b[0].fly();
 }
 
 http://ideone.com/rLiVL
 
 Which is why others were saying you could have B converted to a const
 container of A as this conversion is good for passing a container of B to
 a function that takes a container of A.

Exactly.
Sep 29 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 29 Sep 2010 16:37:49 -0400, Jesse Phillips  
<jessekphillips+D gmail.com> wrote:

 I have shown that what I am talking about is valid for Arrays (a  
 container) but not templates. The issues of actually implementing it is  
 not related to what I was replying to. I introduced it as a benefit to  
 forgetting type information in "generics." I was then told "Having a  
 container of one type should not be castable to a container of
 another type." So I am pointing out we need to remove this feature from  
 arrays right now!

It's a very old bug, please vote: http://d.puremagic.com/issues/show_bug.cgi?id=2095 Also http://d.puremagic.com/issues/show_bug.cgi?id=926 -Steve
Oct 04 2010