Types are useless (?)

235 views
Skip to first unread message

Leksat

unread,
Apr 14, 2012, 5:32:14 PM4/14/12
to General Dart Discussion
The only programming language I know well is PHP. And I tired of it's
inaccuracy. I mean type system: everywhere and everytime I should
check types of arguments I got.
I started looking for Dart language because it supports type
specification (and of course many other great things)... But I found
that it doesn't.

The following code will produce no error:
void test(int i) {
// let's assume, I will pass "i" to an sql query here
// the variable annotated as integer, so I have no worries about
it's using
print(i);
}
test('hacked');

When I annotate function argument as integer, I suppose that I will
have an integer. Not string, not null, not any other type.
If I want to get a dynamic argument, I have Dynamic type for that. Am
I right?

If I run the code described above in checked mode, it will produce an
error, as expected. But, the checked mode is recommended only for
development stage (why?).
If I pass null to test() in checked mode, it will produce no error.
I don't like such state of things. This looks like another PHP.

Dart team, you always ask for feedback...
Please, add non-nullable types (http://code.google.com/p/dart/issues/
detail?id=22).
Please, make checked mode default. Or, at least, make it possible to
set up checked mode from the programm code.

Thanks,
Alexander

Louis Wasserman

unread,
Apr 14, 2012, 5:44:50 PM4/14/12
to Leksat, General Dart Discussion
I think the crux here is why checked mode is recommended only in development.

When you're developing and testing your code, you really do want to see these error messages.  That's obvious enough.  The only difference is that when you're running Dart in production, the Dart team recommends unchecked mode.  Why?

As I understand it, if your code passes your development tests, and doesn't have any type errors, then that should be enough to be confident that it won't have any type errors in production.  (If not, then you're not testing your code enough.) Once you're sure that it won't have any type errors in production, there's no reason to incur the performance overhead of type checking.  You're already confident that your program doesn't have any type errors, so why bother checking more?

That's been my understanding of Dart's approach to typing, and although I'm pretty strongly attached to strong, static type systems myself, I'm satisfied with Dart's approach.

Dirk Detering

unread,
Apr 15, 2012, 8:18:07 AM4/15/12
to Leksat, General Dart Discussion

Beside what Luis said about the 'when' of type checking, there seems to be a little misconception in your argument:
The nullability of a type has nothing to do with the 'when' of the type check, but is an orthogonal concept.

That Dart's current types are nullable put it indeed in a row with PHP, but also with Java and other ones.
Additional non-nullable types are one answer to it and are already discussed afaik. I would rather that Dart embraces more the functional world of algebraic data types, which would allow for things like Maybe (Haskell, Option in Scala).
But that would need more type awareness in the language, not less, as seems to be the preferred way for Dart.

In the end, a nullable reference to a string is a union type of:
  String or Null
With null being the only value of Null. It would be better to avoid null in its current implicit form at all and make that union explicit. Maybe does exactly that.

KR
Det

Leksat

unread,
Apr 15, 2012, 8:38:09 AM4/15/12
to General Dart Discussion
@Louis: the only way to pass all development tests is to check that
given value is integer. The same I should do in PHP.
So, I ask Dart team: please, do not create another PHP.

Bob Nystrom

unread,
Apr 16, 2012, 5:20:23 PM4/16/12
to Dirk Detering, Leksat, General Dart Discussion
On Sun, Apr 15, 2012 at 5:18 AM, Dirk Detering <mail...@googlemail.com> wrote:

Additional non-nullable types are one answer to it and are already discussed afaik. I would rather that Dart embraces more the functional world of algebraic data types, which would allow for things like Maybe (Haskell, Option in Scala).

I really really like algebraic datatypes, but I think they are unnecessary in an OOP language with subtyping like Dart. Subclasses (or implementing interfaces) accomplishes much of what discriminated unions give you in other languages. Sure, there are some differences like how each handles the expression problem and exhaustiveness checking, but I don't know of anything I can do with unions that I can't do with inheritance. Some things are more idiomatic in each flavor (pattern-matching versus visitor pattern), but they both seem to cover about the same ground, I think.

In the end, a nullable reference to a string is a union type of:

  String or Null
With null being the only value of Null. It would be better to avoid null in its current implicit form at all and make that union explicit. Maybe does exactly that.

Union types and algebraic data types are different as I understand them. With an algebraic type, the type tag is explicit, whereas it's implicit in union types. In other words, you can have an algebraic type whose arms have values of the same type (like Either) and still distinguish them. That wouldn't be meaningful with real union types a lá Typed Racket, Pike, etc.

I don't believe Lars and co. are looking to extend the type system, but if they were, I believe real union types would be a much better fit for an optionally-typed language like Dart. They would let you have precise types for valid dynamic functions like:

foo(bool arg) {
  if (arg) 1; else "string";
}

With union types, foo's return type is simply int | String. Algebraic datatypes don't really help you here.

- bob

Paul Brauner

unread,
Apr 17, 2012, 9:55:57 AM4/17/12
to Bob Nystrom, Dirk Detering, Leksat, General Dart Discussion
On Mon, Apr 16, 2012 at 23:20, Bob Nystrom <rnys...@google.com> wrote:


On Sun, Apr 15, 2012 at 5:18 AM, Dirk Detering <mail...@googlemail.com> wrote:

Additional non-nullable types are one answer to it and are already discussed afaik. I would rather that Dart embraces more the functional world of algebraic data types, which would allow for things like Maybe (Haskell, Option in Scala).

I really really like algebraic datatypes, but I think they are unnecessary in an OOP language with subtyping like Dart. Subclasses (or implementing interfaces) accomplishes much of what discriminated unions give you in other languages. Sure, there are some differences like how each handles the expression problem and exhaustiveness checking, but I don't know of anything I can do with unions that I can't do with inheritance. Some things are more idiomatic in each flavor (pattern-matching versus visitor pattern), but they both seem to cover about the same ground, I think.


Something really annoying to implement when emulating pattern matching with visitors is pattern guards with deep patterns, like (haskell syntax):

f (x:y:z:xs) | p z = foo
f (x:xs) = bar

for instance. You have to pass continuations around, play with while and break or duplicate code.

Paul Brauner

unread,
Apr 17, 2012, 9:59:55 AM4/17/12
to Bob Nystrom, Dirk Detering, Leksat, General Dart Discussion
Well, actually deep patterns alone are a pain if you want something efficient.

Paul

Leksat

unread,
Apr 17, 2012, 11:50:06 AM4/17/12
to General Dart Discussion
> foo(bool arg) {
>   if (arg) 1; else "string";
>
> }
>
> With union types, foo's return type is simply int | String. Algebraic
> datatypes don't really help you here.

Sadly, this is exactly what I hate in PHP.
And I still don't understant why we can't just use Dynamic type or
"var" keyword here.

Can somebody tell me what benefits we have from type ignoring in Dart?
Is it for performance purpose? Of for what?
Why we allowing run code with invalid arguments?

Dart was announced as optional typed, but, in fact, it's untyped at
all.

--
Alexander

Seth Ladd

unread,
Apr 17, 2012, 12:11:26 PM4/17/12
to Leksat, General Dart Discussion
Hi Alexander,

For reference, let's look at Java. Many would think that Java has a "strong type system" and that its types prevent, as you say, invalid arguments. However, it's easy to write a Java program that will compile just fine, yet fail at runtime. In your words, it will allow running code with invalid arguments. Here's an example:

import java.util.*;

public class hacked {
  public static void test(int i) {
    System.out.println(i);
  }


  public static void main(String[] args) {
    String msg = "hacked";

    Map cache = new HashMap();
    cache.put("hacked", msg);

    // later
    int hacked = (Integer) cache.get("hacked");
    test(hacked);
  }
}

This code will compile, yet fail at runtime. (Yes, I could have used generics to help a bit, but they aren't mandatory)

I will assert that even with something like Java's type system, which creates barriers and hoops for developers, one can still write incorrect code. In fact, any time you have to cast, you are trying to express something your type system can't express.

So, what if a language has a new perspective on static types? What if a language used static types as annotations, which helped you without getting in your way? Your tools still give you warnings and errors, yet your programs will run without burdensome ceremony.

There is a direct tradeoff between constraining type systems that disallow any ever possible error (which is also probably impossible), and developer productivity. Remember that Dart is trying to appeal to a wide array of developers, from JavaScript developers that deal only in functions and have never seen a type, to Java/C# developers that love their tools, static types, and structure. Dart is optimizing for developer productivity without sacrificing structure or tooling. Its optional types help you when you need them, but don't create unnecessary barriers.

I personally felt more free once I realized that no mainstream language actually had a perfect type system. A combination of tool support, static analysis, checked mode assertions, and unit tests can allow me to feel just as safe, yet more productive.

Thank you for your questions, it's healthy to be skeptical. :)

Seth

Leksat

unread,
Apr 17, 2012, 12:31:34 PM4/17/12
to General Dart Discussion
> Thank you for your questions, it's healthy to be skeptical. :)

Thanks for your answers! They make sense.
I just grew up to static types... Maybe it's time to grow higher :)

--
Alexander

Colin Putney

unread,
Apr 17, 2012, 2:56:28 PM4/17/12
to Leksat, General Dart Discussion
On Tue, Apr 17, 2012 at 8:50 AM, Leksat <alex....@gmail.com> wrote:

> Sadly, this is exactly what I hate in PHP.
> And I still don't understant why we can't just use Dynamic type or
> "var" keyword here.
>
> Can somebody tell me what benefits we have from type ignoring in Dart?
> Is it for performance purpose? Of for what?
> Why we allowing run code with invalid arguments?
>
> Dart was announced as optional typed, but, in fact, it's untyped at
> all.

Be careful when comparing any type system to PHP. In the example Bob
gave, the function foo() has the type int | String, which means it
might return either an integer or a string. In PHP, the equivalent
function would return a value that is both an integer and a string,
and can be used as either in subsequent operations.

Personally I don't like PHP's typelessness either. But Dart's system
of dynamic typing with optional type annotations is quite different
from that. Dart is not "untyped" at all. It does strict type checking
at runtime - if you try to do math on a string, it won't just use a
zero value, it'll throw an exception. You can also run it with type
assertions turned on, so that you'll get an explicit type error if the
runtime types don't match your annotations. And finally, you can
statically type-check a Dart program to find conflicts between your
annotations.

None of that is true in PHP.

Cheers,

Colin

Sylvain Robez-Masson

unread,
Oct 22, 2012, 4:14:14 AM10/22/12
to mi...@dartlang.org, alex....@gmail.com
I don't understand why in production we can do a thing like that :
main() {
    var names = new List<String>();
    names.add('Seth');
    names.add(3);
    print(names);
}

Someone could tell me why the production don't care of variable's type ?

Ladislav Thon

unread,
Oct 22, 2012, 5:23:43 AM10/22/12
to mi...@dartlang.org
I don't understand why in production we can do a thing like that :
main() {
    var names = new List<String>();
    names.add('Seth');
    names.add(3);
    print(names);
}

Someone could tell me why the production don't care of variable's type ?

Because Dart is a dynamically typed language. Type annotations are there for documentation and tooling purposes, not for enforcing the language's world view on the programmer.

LT

Steve Walker

unread,
Oct 22, 2012, 5:46:32 AM10/22/12
to mi...@dartlang.org, alex....@gmail.com
In production mode, Dart doesn't complain about the incompatible type assignment because, by running in unchecked mode, you haven't asked it to.

At run time, this code works because the list structure actually deals with objects. The type restriction imposed on the list (to only hold strings) is only applied in checked mode. If you extend your example like this:

void main() {

   
var names = new List<String>();
    names
.add('Seth');
    names
.add(3);
   
print(names);

   
   
// Works when treating all elements as objects
    names
.forEach((i) => print(i.hashCode()));
   
   
// Breaks when treating all elements as strings
    names
.forEach((n) => print(n.length));
}


you'll see that as soon as you try to treat the rogue object (3) as a string Dart does complain. Remember, Dart is a dynamic language with optional static typing - checked mode is how you exercise that option.

Sylvain Robez-Masson

unread,
Oct 22, 2012, 6:09:29 AM10/22/12
to mi...@dartlang.org, alex....@gmail.com
Your answers doesn't really answer to mine.
In my opinion the List<String> syntax is useless if you need to check variable type everywhere in your code.

Steve Walker

unread,
Oct 22, 2012, 6:17:42 AM10/22/12
to mi...@dartlang.org, alex....@gmail.com
If you run the sample in checked mode it will halt at 

name.add(3);

and complain that 3 is not a string. Type-checking is enabled by running in checked mode.

Sylvain Robez-Masson

unread,
Oct 22, 2012, 6:29:07 AM10/22/12
to mi...@dartlang.org, alex....@gmail.com
I still don't understand why it's not checked in production mode

chl

unread,
Oct 22, 2012, 6:30:06 AM10/22/12
to mi...@dartlang.org, alex....@gmail.com
check mode is slowwww..........

Ahmet A. Akın

unread,
Oct 22, 2012, 7:21:06 AM10/22/12
to mi...@dartlang.org, alex....@gmail.com
Because in checked mode there are a lot of type related assertions inserted in the code. Thus it is noticeably slow.

Steve Walker

unread,
Oct 22, 2012, 7:23:06 AM10/22/12
to mi...@dartlang.org, alex....@gmail.com
Running in checked mode affects performance as type-checking requires extra time and resources. You could run checked mode in production but this would significantly affect the performance of your app and not really provide any benefit as you would have detected any type-safety issues during development.
Reply all
Reply to author
Forward
0 new messages