#981 type cast construct

jessevdam Tue 16 Feb 2010

It often happens you get a construct like

if(somevar is SomeType) {

somevar2 := (SomeType)somevar
//usage of field defined in SomeType
somevar2.myfield = 1

}

Is it possible to make something like:

if(somevar iscast SomeType) {

//usage of field defined in SomeType
somevar.myfield = 1

}

In which the iscast operator automatically changes the scope in such a way the somevar becomes of type SomeType within the enclosed block.

This will prevent us from constantly having to a type cast and define a new variable, which we also have to give a new name.

Something like this can also be done in case we have a switch statement

switch (p) {

case p iscast ColorPoint:
  p.aColorPointField = 1
case p iscast Point:
  p.aPointField = 1
default:

}

MoOm Tue 16 Feb 2010

This is something that could indeed be really interesting to have, as it would reduce the number of casts we need to do and potentially detect some bugs at compile-time. I don't see why we'd need a new keyword for this though: "is" can already serves this purpose I guess. For example:

if (var is SomeType)
{
   //In this block, the compiler could infere that "var" is of type "SomeType"
}

This could even be used for null-check tests. For example:

SomeType? var := ...
if (var != null)'
{
   //In this block, the compiler could infere that "var" is of type "SomeType"
}

In the Delight programming language, this approach is used to check for any possible null-pointer exceptions at compile-time. So you know that when your code compiles, a null-pointer exception can never happen, which is really nice imho. I think the Nice programming language does the same thing

Yuri Strot Tue 16 Feb 2010

You can find some comments on this stuff in this discussion: #859

So you can use dynamic invoke:

if (somevar is SomeType) {
  somevar->myfield = 1
}

MoOm Tue 16 Feb 2010

Dynamic invoke is slower than static invoke and it does not offer the compile-time safety provided by the proposed solution (with dynamic invoke, if you make a typo in myfield, it'll just crash). So this solution is not as nice as the proposed one imho.

jessevdam Tue 16 Feb 2010

I agree with MoOm.

The self inference construct would even be better. It is also used in other languages.

But with self inference do we have to take care with the following situation in which we have a switch statement

switch(SomeType typeof) {

case SubType1OfSomeType#:
case SubType2OfSomeType#:
  //some statements
  //In case of self inference we will get a conflict.
default:

}

I think the best thing would be to great a warning and do nothing in this case. So you still have to do a type cast in this situation.

helium Tue 16 Feb 2010

Basically the same thing was proposed a few days ago in topic 970.

brian Tue 16 Feb 2010

I personally don't like the idea of changing the type of a local variable b/w scopes. It creates lots of complication with JVM verification and typing heap allocated closure variables. Plus I think it would making IDE tooling more difficult, so I think whatever the solution it should require defining a new local variable.

I almost always use as instead of is:

x := y as SubFoo
if (x != null) ...

Which is we did some construct for handling null would work well with the as operator.

MoOm Tue 16 Feb 2010

Agreed on the IDE tooling that will become indeed more complicated. About the complication of the VM, couldn't it be solved by making the compiler rewrite the above snippets by introducing implicit local variables. For example:

Obj var := ...
if (var is SomeType)
{
   var.methodFromSomeType()
}

SomeType? var := ...
if (var != null)
{
   var.safeMethodCall()
}

would be rewritten by the compiler as:

Obj var := ...
if (var is SomeType)
{
   someTypeVar := (SomeType)var
   someTypeVar.methodFromSomeType()
}

SomeType? var := ...
if (var != null)
{
   SomeType nonNullVar := (SomeType)var
   nonNullVar.safeMethodCall()
}

This way, it won't complicate the VM. This is actually what the developer would probably have written anyway.

Of course, for the null-checking part, it'd be useful only if var.safeMethodCall() would trigger a compile-time error when var is a nullable-type (like in Delight).

Login or Signup to reply.