View mode: basic / threaded / horizontal-split · Log in · Help
April 20, 2005
Re: Object.opCmp - about time we came to a decision
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:d3q2tm$1pag$1@digitaldaemon.com...
> > Who said anything about heteregeneous types? Object[] means whatever,
> > including Foo[], because you can implicitly cast Foo[] to Object[]. I.e.
> > everything is an Object.
>
> hmm. It is pretty scary if we are allowed to do
> class Foo{int foo;}
> void main() {
>   Foo[] x;
>   x.length = 2;
>   Object[] y = x; // implicitly cast
>   y[0] = new Object;
>   x[0].foo = 10; // Object is not a Foo - yikes!
> }
>
>
>

Don't be scared so easily.  :)

Seriously though, the only problem with that is the potential that the programmer may not have meant to do an identity assignment when they typed "y=x" and therefore may not have planned for the side effects of x and y having the same identity.  A situation that could be easily avoided if separate value and identity assignment operators were introduces.

I don't see anything being done there that lacks the "potential to be useful" in the right situation.  Sure, it could be misused, but that's true of anything that can be used at all.  The only hazard I see is the potential for it to be done accidentally, and that's not likely.

TZ
April 20, 2005
Re: Object.opCmp - about time we came to a decision
"TechnoZeus" <TechnoZeus@PeoplePC.com> wrote in message 
news:d457b2$2oai$1@digitaldaemon.com...
> "Ben Hinkle" <ben.hinkle@gmail.com> wrote in message 
> news:d3q2tm$1pag$1@digitaldaemon.com...
>> > Who said anything about heteregeneous types? Object[] means whatever,
>> > including Foo[], because you can implicitly cast Foo[] to Object[]. 
>> > I.e.
>> > everything is an Object.
>>
>> hmm. It is pretty scary if we are allowed to do
>> class Foo{int foo;}
>> void main() {
>>   Foo[] x;
>>   x.length = 2;
>>   Object[] y = x; // implicitly cast
>>   y[0] = new Object;
>>   x[0].foo = 10; // Object is not a Foo - yikes!
>> }
>>
>>
>>
>
> Don't be scared so easily.  :)
>
> Seriously though, the only problem with that is the potential that the 
> programmer may not have meant to do an identity assignment when they typed 
> "y=x" and therefore may not have planned for the side effects of x and y 
> having the same identity.  A situation that could be easily avoided if 
> separate value and identity assignment operators were introduces.
>
> I don't see anything being done there that lacks the "potential to be 
> useful" in the right situation.  Sure, it could be misused, but that's 
> true of anything that can be used at all.  The only hazard I see is the 
> potential for it to be done accidentally, and that's not likely.

Here's another example that might be more common:
class Foo{}
class Bar:Foo{}
void clamp(Foo[] x) { // cheesy function that changes x
 foreach(inout Foo y; x) {
   if (y < 0)  y = new Foo(0);
 }
}
...
Bar[] y;
...
fill(y); // y potentially has a Foo in it - a type violation.

Implicitly casting shouldn't open up such a large hole in the type system. 
At least in C violating the type system requires a cast.
April 20, 2005
Re: Object.opCmp - about time we came to a decision
> Here's another example that might be more common:
> class Foo{}
> class Bar:Foo{}
> void clamp(Foo[] x) { // cheesy function that changes x
>   foreach(inout Foo y; x) {
>     if (y < 0)  y = new Foo(0);
>   }
> }
> ....
> Bar[] y;
> ....
> fill(y); // y potentially has a Foo in it - a type violation.

But here, you're calling basically fillSomeElementsWithFoos(Bar[]). You 
obviously can't expect the result to be Bars only.. I mean, the problem 
is not the implicit cast, but the type of y, when used with fill(). Even 
if you call fill(cast(Foo[])y), it can still contain a Foo, while its 
type is Bar[]..

My point is that you need to know what your functions do, otherwise 
you'll run into problems, with implicit casting of arrays or not.

If implicit casting of arrays were to be removed, it would mean that 
each function that works on an array works exactly on that kind of array 
and nothing else. The result would be just requiring a ton of casts, 
which solves nothing, yet could cause more problems than it solves - in 
the case above, you would type "fill(cast(Foo[])y)". But then, when you 
write fill(Bar[]) to handle Bar[] filling, it won't get called, because 
you cast the real type away..


xs0
April 20, 2005
Re: Object.opCmp - about time we came to a decision
"xs0" <xs0@xs0.com> wrote in message news:d45psv$l74$1@digitaldaemon.com...
>
>> Here's another example that might be more common:
>> class Foo{}
>> class Bar:Foo{}
>> void clamp(Foo[] x) { // cheesy function that changes x
>>   foreach(inout Foo y; x) {
>>     if (y < 0)  y = new Foo(0);
>>   }
>> }
>> ....
>> Bar[] y;
>> ....
>> fill(y); // y potentially has a Foo in it - a type violation.
>
> But here, you're calling basically fillSomeElementsWithFoos(Bar[]). You 
> obviously can't expect the result to be Bars only.. I mean, the problem is 
> not the implicit cast, but the type of y, when used with fill(). Even if 
> you call fill(cast(Foo[])y), it can still contain a Foo, while its type is 
> Bar[]..

A core principle of upcasting is substitutability. If Bar is derived from 
Foo then everything that takes a Foo can take a Bar. With arrays, though, an 
array of Foo cannot be substituted with an array of Bar since an array of 
Foo can hold an aribitrary Foo while an array of Bar cannot. Implicitly 
upcasting containers is a big type safety hole if the result is allowed to 
change the contents of the container.

> My point is that you need to know what your functions do, otherwise you'll 
> run into problems, with implicit casting of arrays or not.

Sure, but with enough care we wouldn't have any bugs at all and we'd have no 
need for type checking or type-safety. Imagine how hard it would be to track 
down something as subtle as this.

> If implicit casting of arrays were to be removed, it would mean that each 
> function that works on an array works exactly on that kind of array and 
> nothing else.

True, but that's life. I believe sacrificing type-safety is too high a price 
to pay for the convenience of implicit array coversions. In my D coding, for 
instance, I haven't ever needed implicit array conversions.

> The result would be just requiring a ton of casts, which solves nothing, 
> yet could cause more problems than it solves - in the case above, you 
> would type "fill(cast(Foo[])y)". But then, when you write fill(Bar[]) to 
> handle Bar[] filling, it won't get called, because you cast the real type 
> away..

Casting is the accepted way to blow away type safety. Let's keep it that 
way.
April 20, 2005
Re: Object.opCmp - about time we came to a decision
Ben Hinkle wrote:
> Implicitly 
> upcasting containers is a big type safety hole if the result is allowed to 
> change the contents of the container.

> Casting is the accepted way to blow away type safety. Let's keep it that 
> way. 

See, it's not that simple. To have more type safety, you'd require more 
casts, but they result in less type safety, so it may actually be 
conterproductive..

Java and C++ both allow implicit array upcasts, too, so I wouldn't say 
that people can't live with it?

OTOH, If you look at Java's generics spec, they addressed this issue 
somewhat by having parameters be one of (with List as an example)
List<T> - accepts exactly T
List<? super T> - accepts T and T's supertypes
List<? extends T> - accepts T and T's subtypes

The first is read/write, the second is write-only, the third is 
read-only, for obvious reasons. Considering how write-only is 
significantly rarer than the other two, perhaps the best option with D 
would be to get support and a new syntax for demanding an exact type in 
function parameters, which is where most of the problem is. Perhaps

void func(Type! a)
void func(Type![] a)
void func(Type!(int)! a)
void func(Type!(int)![] a)

Read-only functions would work as they do now, which is fine because 
they don't suffer from type unsafety. Read/write functions would be able 
to demand an exact type (which may or may not be useful outside the 
context of arrays, but I don't see why it shouldn't be allowed). 
Finally, for write-only functions, I guess the way to go would be again 
requiring an exact type, which'd require an explicit cast. However,

this case of casting is not as problematic, because if you have like a 
FooSuperclass[] and cast it to Foo[] when calling a func, you're still 
keeping it locally as a FooSuperclass[], which it still is even after it 
gets filled with Foos (unlike casting a Subclass[] to Foo[], which is 
then no longer a Subclass[]).

Finally, to solve the local issue of

Foo[] a=...;
Object[] b=a;
b[0]=new Object;
a[0].do();

I'd say that implicit casting of arrays can only be done when calling 
functions, where it's only really needed anyway. Locally, you can always 
use the other type in the first place, I guess..

Thoughts?


xs0
April 20, 2005
Re: Object.opCmp - about time we came to a decision
"xs0" <xs0@xs0.com> wrote in message news:d4632l$uke$1@digitaldaemon.com...
>
> Ben Hinkle wrote:
>> Implicitly upcasting containers is a big type safety hole if the result 
>> is allowed to change the contents of the container.
>
>> Casting is the accepted way to blow away type safety. Let's keep it that 
>> way.
>
> See, it's not that simple. To have more type safety, you'd require more 
> casts, but they result in less type safety, so it may actually be 
> conterproductive..

I'm suggesting the user be more explicit about when they are risking type 
safety. The implicit cast is hiding some potentially very dangerous code.

> Java and C++ both allow implicit array upcasts, too, so I wouldn't say 
> that people can't live with it?

Note Java allows the implicit cast but doesn't allow the assignment that 
would break the type-safety.
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html#11430
I'm not suggesting D go the Java route and store all the run-time array type 
information. I do suggest D make the coder more explicitly acknowledge when 
they are taking a risk with type safety. I agree C++ allows implicit pointer 
upcasting but everyone grumbles about C++ type-safety holes like that. It's 
one of C++'s weaknesses in following C so closely.
April 20, 2005
Re: Object.opCmp - about time we came to a decision
Ben Hinkle wrote:
>>>Implicitly upcasting containers is a big type safety hole if the result 
>>>is allowed to change the contents of the container.
>>
>>>Casting is the accepted way to blow away type safety. Let's keep it that 
>>>way.
>>
>>See, it's not that simple. To have more type safety, you'd require more 
>>casts, but they result in less type safety, so it may actually be 
>>conterproductive..
> 
> I'm suggesting the user be more explicit about when they are risking type 
> safety. The implicit cast is hiding some potentially very dangerous code.

I agree, but I don't think forcing them to explicitly cast is the best 
solution. See my previous post for what I'd suggest. Another option is 
simply using inout, although in that case you can't cast even if you 
want to (at least not very easily - you need a new var and a cast 
back).. btw, what I suggested is exactly the same regarding type safety 
as inout, the only inout's downside is that the caller's reference can 
be overwritten..


>>Java and C++ both allow implicit array upcasts, too, so I wouldn't say 
>>that people can't live with it?
> 
> Note Java allows the implicit cast but doesn't allow the assignment that 
> would break the type-safety.

True, yet it still only happens at run-time, and it may even be unneeded:

Object[] blah=someFunc(); // returns a new String[];
blah[0]=new Whatever(blah[0]);


Although it's true - in D such an error will most probably not even get 
detected right away, which can probably cause quite a havoc, if you're 
lucky.. Again, I don't think forcing explicit casts will help; if a 
change is going to happen, it should be where the function is, not where 
the caller is (in other words, type safety should be enforced already 
when defining functions, not when calling them).


> I'm not suggesting D go the Java route and store all the run-time array type 
> information. I do suggest D make the coder more explicitly acknowledge when 
> they are taking a risk with type safety. 

> everyone grumbles about C++ type-safety holes. It's
> one of C++'s weaknesses in following C so closely. 

Agreed on both counts.


xs0
April 20, 2005
Re: Object.opCmp - about time we came to a decision
xs0 wrote:
> Ben Hinkle wrote:
> 
>>>> Implicitly upcasting containers is a big type safety hole if
>>>> the result is allowed to change the contents of the container.
>>> 
>>>> Casting is the accepted way to blow away type safety. Let's
>>>> keep it that way.
>>> 
>>> See, it's not that simple. To have more type safety, you'd
>>> require more casts, but they result in less type safety, so it
>>> may actually be conterproductive..
>> 
>> I'm suggesting the user be more explicit about when they are
>> risking type safety. The implicit cast is hiding some potentially
>> very dangerous code.
> 
> I agree, but I don't think forcing them to explicitly cast is the
> best solution. See my previous post for what I'd suggest. Another
> option is simply using inout, although in that case you can't cast
> even if you want to (at least not very easily - you need a new var
> and a cast back).. btw, what I suggested is exactly the same
> regarding type safety as inout, the only inout's downside is that the
> caller's reference can be overwritten..
> 
>>> Java and C++ both allow implicit array upcasts, too, so I
>>> wouldn't say that people can't live with it?
>> 
>> Note Java allows the implicit cast but doesn't allow the assignment
>>  that would break the type-safety.
> 
> True, yet it still only happens at run-time, and it may even be
> unneeded:
> 
> Object[] blah=someFunc(); // returns a new String[];
> blah[0]=new Whatever(blah[0]);

Anybody writing that piece of code is asking for First Blood. Out of his 
own nose.

There are limits to things. We don't want D to be jerk-proof. Probably 
there ought to be a law that says this kind of people should not have 
cutlery in the kitchen. (Why? Well, they might carve the dog or the 
postman, just out of ignorance: Oh, I just wanted to check if this knife 
is as sharp as they say on TV, Officer.)

> Although it's true - in D such an error will most probably not even
> get detected right away, which can probably cause quite a havoc, if
> you're lucky.. Again, I don't think forcing explicit casts will help;
April 20, 2005
Re: Object.opCmp - about time we came to a decision
>> True, yet it still only happens at run-time, and it may even be
>> unneeded:
>>
>> Object[] blah=someFunc(); // returns a new String[];
>> blah[0]=new Whatever(blah[0]);
> 
> Anybody writing that piece of code is asking for First Blood. Out of his 
> own nose.

Why exactly? The point was that

a) the code handles any Object
b) Java would needlessly throw an exception here


> There are limits to things. We don't want D to be jerk-proof. Probably 
> there ought to be a law that says this kind of people should not have 
> cutlery in the kitchen. (Why? Well, they might carve the dog or the 
> postman, just out of ignorance: Oh, I just wanted to check if this knife 
> is as sharp as they say on TV, Officer.)

Bah, I can think of some other laws as well :P


xs0
April 20, 2005
Re: Object.opCmp - about time we came to a decision
xs0 wrote:
> 
>>> True, yet it still only happens at run-time, and it may even be
>>> unneeded:
>>>
>>> Object[] blah=someFunc(); // returns a new String[];
>>> blah[0]=new Whatever(blah[0]);
>>
>>
>> Anybody writing that piece of code is asking for First Blood. Out of 
>> his own nose.
> 
> 
> Why exactly? The point was that
> 
> a) the code handles any Object
> b) Java would needlessly throw an exception here

If the code handles "any Object", then why be surprised if the compiler 
doesn't catch the situation where you suddenly don't want it to?

>> There are limits to things. We don't want D to be jerk-proof. Probably 
>> there ought to be a law that says this kind of people should not have 
>> cutlery in the kitchen. (Why? Well, they might carve the dog or the 
>> postman, just out of ignorance: Oh, I just wanted to check if this 
>> knife is as sharp as they say on TV, Officer.)
> 
> 
> Bah, I can think of some other laws as well :P
> 
> 
> xs0
4 5 6 7 8 9
Top | Discussion index | About this forum | D home