Casts in Dart

1,248 views
Skip to first unread message

Jeff Bailey

unread,
Feb 9, 2012, 6:45:29 PM2/9/12
to mi...@dartlang.org, Bradley Nelson
I'm taking in an object by JSON like so:

var data = JSON.parse(msg.data.substring(prefix.length));

I'd like to do something like dynamic_cast after it based off of the contents of the first element, so:

    switch (data[0]) {
      case NaclMsg.NACL_MSG_PRINT_GLYPH:
        // Some sort of cast to prove that the rest of the list is List<int>

      case NaclMsg.NACL_MSG_PUTSTR:
        // Some sort of cast to prove that the remaining arguments are Int, Int, String.

The language spec 0.07 hints at casts, typeof, etc not existing in:

Reified type information reflects the types of objects at runtime and may always be queried by dynamic typechecking constructs (the analogs of instanceOf, casts, typecase etc. in other languages). Reified type information includes class and interface declarations, the class of an object, and type arguments to constructors.

but doesn't indicate how I'd do a runtime check or a cast to ensure that I'm actually holding the expected type in the final variable.

Any hints are appreciated! =)
Jeff Bailey | Software Engineer | jeffb...@google.com | Google


Sam McCall

unread,
Feb 9, 2012, 6:56:45 PM2/9/12
to Jeff Bailey, mi...@dartlang.org, Bradley Nelson
The 'is' operator compares a value with a type and returns a boolean.

if (x is String)
if (x is List) // true for all lists
if (x is List<int>) // true for lists created like new List<int>, <int>[], etc.
// doesn't guarantee that all entires are ints.

Gilad Bracha

unread,
Feb 9, 2012, 6:57:14 PM2/9/12
to Jeff Bailey, mi...@dartlang.org, Bradley Nelson
if (data is List<int>) ...

Mind you, in your case data is probably a List<Dynamic> which will work just fine.  But the static checker may be more helpful to you if you write:

List<int> intData = data;

Later in your code, you'll get type checking based on the assumption that you have a list of int.
--
Cheers, Gilad

John Messerly

unread,
Feb 9, 2012, 6:56:59 PM2/9/12
to Jeff Bailey, mi...@dartlang.org, Bradley Nelson
On Thu, Feb 9, 2012 at 3:45 PM, Jeff Bailey <jeffb...@google.com> wrote:
I'm taking in an object by JSON like so:

var data = JSON.parse(msg.data.substring(prefix.length));

I'd like to do something like dynamic_cast after it based off of the contents of the first element, so:

    switch (data[0]) {
      case NaclMsg.NACL_MSG_PRINT_GLYPH:
        // Some sort of cast to prove that the rest of the list is List<int>


If you're running in checked mode:
for (int e in data) {  // this will throw a TypeError if "e" is not an int
  // ...
}

If you want the check to work regardless of mode:
for (var e in data) {
  if (e is! int) throw new Exception('not an int');
}



      case NaclMsg.NACL_MSG_PUTSTR:
        // Some sort of cast to prove that the remaining arguments are Int, Int, String.


In checked mode:
     assert(data.length == 4);
int arg1 = data[1];
int arg2 = data[2];
String arg3 = data[3];

If you want it to check regardless of mode:
     if (data.length != 4) throw new Exception('invalid length');
int arg1 = data[1];
int arg2 = data[2];
String arg3 = data[3];
if (arg1 is! int || arg2 is! int || arg3 is! String) {
  throw new Exception('invalid argument type');
}
 
Generally I prefer the checked mode pattern. That's the whole point of having the types in the code :-)

- John

John Messerly

unread,
Feb 9, 2012, 7:15:24 PM2/9/12
to Gilad Bracha, Jeff Bailey, mi...@dartlang.org, Bradley Nelson
Does that work? I thought we had a bug where:

interface Foo {
  doExcitingStuff();
}

List<Foo> foos = ...;

// The following might blow up with a NoSuchMethodError instead of a TypeError,
// because there's no runtime check that the thing you got from List<Foo>
// is actually a Foo. It might be a completely unrelated class Bar, which may
// or may not have a "doExcitingStuff" method.
foo[0].doExcitingStuff();

So for sufficiently paranoid code, the only way to be safe is to check every element. (Personally I don't think this is a big problem, but it's an interesting corner case.)

- John

Jeff Bailey

unread,
Feb 9, 2012, 7:18:03 PM2/9/12
to John Messerly, mi...@dartlang.org, Bradley Nelson
Thanks all!  It looks like a combination of all three approaches is the right thing.  First List<Dynamic> when reading in from the JSON so that I'm not resorting to var there, and then either is (when I have a range of types), or specifying the type in a loop when I'm walking across it.

I've got the warnings gone for now and will do the checking on all the options over the next couple of days.

Jeff Bailey | Software Engineer | jeffb...@google.com | Google




Reply all
Reply to author
Forward
0 new messages