
Why Dart Types Are Optional and Unsound - fogus
http://www.dartlang.org/articles/why-dart-types/
======
jashkenas
Also, writing this:

    
    
        > We don't want Dart to be a testbed for active programming
        > languages research, but I think we're open to taking up
        > ideas after they become well understood and unsurprising,
        > a.k.a. a little bit boring.
    

... after saying this in the first paragraph:

    
    
        > Dart uses types in a way that might seem strange. Most
        > popular languages that offer a type system use it very 
        > differently. If you're familiar with types in Java, Haskell, 
        > Scala, or any statically typed language, you may wonder 
        > why on earth Dart makes the choices that it does.
    

... makes me wonder why on earth Dart makes the type system choices that it
does ;)

~~~
roestava
That's a good point to make. Miguel de Icaza has said that after taking a
brief look at Dart he thought it was pretty academic. Maybe he was refering to
more than the optional typing that Dart makes use of. The truth though is that
Dart is in some ways experimental while folks such as Miguel are sitting on
already established tech in c#. They aren't going to welcome potential
competitors.

------
charliesome
_Don't you want strong typing for better performance?_ _That's what I thought,
too. The VM designers say that in practice, type guarantees really don't help
them nearly as much as you might think, because type checks are not a major
drain on performance._

No, but you can generate better code if you know _exactly_ what types you're
playing with ahead of time.

Say you have a function like this:

    
    
        void foo(SomeClass obj) {
            obj.bar();
        }
    

That could be compiled to just a straight 'jmp SomeClass::bar', whether you're
compiling natively or to a VM.

If you don't have static types, the best code you can output is something
along the lines of this:

    
    
        fn = lookup(obj, "bar")
        jmp fn
    

Of course there are tricks that you can use to optimize this second case a bit
that involve fancy static analysis, fancy JIT business, etc. but the point is
that you will _never_ generate better code than just a single jump to the
right code, based on the types you know at compile time in a static language.

~~~
extension
In any sensible OO language (i.e. not C++) all method calls will be virtual,
so there is always some sort of dynamic lookup involved.

~~~
AndrewDucker
In C# you have to specify that a method is virtual if you want people to be
able to override it. This makes it clear where you expect people to insert
their changes, allows you to design extra safety into those points, and makes
the code faster.

------
jashkenas

        > Correctness is easier to achieve for a VM that doesn't
        > rely on static soundness guarantees, because you don't
        > need the complexity of bytecode verification.
    

I don't follow. You only need to verify bytecode if a), you have bytecode in
the first place, and b), you assume the existence of a hostile compiler or
other external bytecode source. Neither of these apply to Dart.

~~~
roestava
Maybe with static typing and bytecodes the author was meaning lower level and
hence riskier stuff. Not that Dart was lower level.

By being higher level Dart can work from a subset, keeping the surface area
smaller as a result.

------
lmkg
So what do types and type annotations actually _do_ in Dart? I may have missed
something obvious, but it looks like all the code samples given in the article
will all pass static verification. Can someone give me an example of a code
error that Dart will catch statically at compile time? My biggest confusion
about Dart's type system (or at least its static one) is that it simply
doesn't seem to do very much, so I wonder why it exists at all.

~~~
roestava
Hehe. I guess Dart users are troubled by it as well because the way it works
is surprising based on our previous experiences. Basically you can run the
program in checked mode so you do get more feedback from the usage of the
types. But checked mode is meant for development as it isn't as optimized as
in other languages. We need to recall that Dart gets translated into
JavaScript and adding type checks and stuff to all the code required puts an
extra burden on it that can be hard to justify.

All in all, you should run in checked mode for more feedback. The idea is that
you get warnings when stuff is bad. When stuff is super bad you get runtime
exception.

Dart is optimist and will give you warnings and let your code run until it
cannot.

~~~
JoshTriplett
I certainly agree that the translated JavaScript shouldn't need to enforce
types in any way, unless Dart provides some kind of "downcasting" mechanism to
give something a type it doesn't already have. However, that only applies if
the Dart compiler doesn't statically enforce the types when compiling the code
to JavaScript.

For one example: Haskell's strong static types all go away when you compile;
the generated code does not do any type enforcement or verification.

The biggest thing I hoped the article would talk about got shot down in the
very first section, which just said "Dart is dynamically typed" and explicitly
dismissed any need to justify that, other than by saying "Users of dynamically
typed languages ... will understand why we chose this".

I honestly can't even begin to understand why people consider dynamic typing a
feature; when I saw the headline I hoped to see an interesting justification,
but instead I saw it taken as a given and then used to justify many other
things. I agree that almost all of those things do follow naturally from the
assumption of dynamic typing, but I'd still like to know the rationale for
that assumption.

The only justification I've ever seen for dynamic typing amounted to "because
I like duck typing". However, a static type system can trivially enforce duck
typing.

------
carsongross
Pragmatically, typing is for tooling first, catching errors second, soundness
a distant third.

My tastes run towards a C#-like language ( _cough_ Gosu): statically typed
with inference, simple generics (covariance), proper function types to fill in
most of the covariant holes, and a dynamic type escape hatch, just in case.

But of course they would.

------
ot

      mammal = cow;      // [1]
      pig = mammal;      // [2] Checks OK statically, but now pig holds a Cow.
      print(pig.oink()); // [3] NoSuchMethodException if we get this far.
    

As far as I understand this means that no precondition can be encoded in the
variable type. A function with a Pig argument can still cause a
NoSuchMethodException exception because the argument can actually hold a Cow
instance.

~~~
jbri
You still have a precondition encoded in the parameter type. It's just a
precondition for the programmer to see and understand, rather than one for the
machine to rigorously enforce.

------
azakai
>> Don't you want strong typing for better performance?

> That's what I thought, too. The VM designers say that in practice, type
> guarantees really don't help them nearly as much as you might think, because
> type checks are not a major drain on performance.

If this is the case, what is supposed to make Dart faster than JavaScript? It
sounds like they will end up around the same speed.

~~~
jashkenas
The main difference that _may_ allow Dart to run faster than JavaScript isn't
type checks, but objects having static shape at runtime.

In JavaScript, I can write this:

    
    
        var dog = new Animal();
        dog.name = "Fido";
    

... adding a new field to the "dog" object, even though other objects of the
same class may have no such field. Objects that share common sets of fields
are the famous "hidden classes" that V8 is able to optimize.

You can't write the above example in Dart. Dart doesn't have to work as hard
as V8 to discover and cache hidden classes, because the shape of an object is
statically fixed to be the same as its class.

~~~
azakai
Yes, but how much of a slowdown is it to manage hidden classes? Furthermore,
in the most performance sensitive code, you might not even have classes at
all, just raw calculations (for example on typed arrays), which Dart will be
no faster than JS at.

~~~
DasIch
If you know the shape you can reduce attribute access to an array lookup, if
you don't attribute access requires a hash table lookup. That is a problem for
performance and memory consumption.

~~~
azakai
Sure, but again, (1) JS engines can and do infer the shape at runtime using
hidden classes, and they also get array lookups that way (and not hash table
lookups), and (2) I suspect these lookups are not even on the critical path of
typical performance-intensive code, but that's speculation of course.

------
dextorious
One thing I don't get (not knowing much about type theory, and only having
implemented a toy C++ subset compiler in a university class once):

Take a dynamically typed language, say, Python:

a = 1

a = "foo"

What disadvantage would you have if the language used type inference to set
__a __to a static type of int when it encountered it?

a = 1

a = "foo" # compile/interpretation time error, "a is an int"

1) You get the speed/optimizations + tooling of static typing. 2) You get the
dynamic typing benefit of not messing with type definitions etc.

Do people really do stuff like changing the type of a variable in normal
Python use, anyway? Usually when I set something to something, I keep it in
the same type.

Is there a disadvantage, besides having to initialize every variable upfront?
Polymorphism/Generics are orthogonal to this, no?

Are there any languages that do it this way?

~~~
DasIch
Type Inference only works nicely if your have static and strong types.
Heterogenous data structures are non-trivial in such a language, duck typing
doesn't work anymore etc.

In other words people do use these features, they use these features a lot and
that is not a problem. You are just using an overly trivial example in which
you make assumptions without considering all the consequences.

~~~
dextorious
"""Heterogenous data structures are non-trivial in such a language"""

Why would they be? You just need a common parent type, like object, or
something like Objective-C's "id" type, to indicate that a structure/method
can accept any type.

So:

a = 1 # int

b = "foo" # string

c = Cat() # cat object

d = Singer() #singer object

you could have a built-in, say list, structure:

mylist = [a, b, c]; mylist.append(d)

or

myadt = CustomDataType()

myadt.add(c); myadt.add(d);

"""duck typing doesn't work anymore etc."""

Wikipedia: "duck typing is a style of dynamic typing in which an object's
current set of methods and properties determines the valid semantics, rather
than its inheritance from a particular class or implementation of a specific
interface".

So, why would duck typing not work? Duck typing is about the ability to call
methods on any type that implements them. It's irrelevant if the type is
static, not? Say:

foreach item in myadt: item.sound()

Cat and Singer could be from totally different objects hierarchies, and the
compiler/language would know that both implement "sound()" and let you call
it.

If an object on myadt doesn't implement sound() you get a runtime error.

"""You are just using an overly trivial example in which you make assumptions
without considering all the consequences."""

Emm, the whole point of my comment was in me EXPLICITLY ASKING for possible
consequences. Which you kinda missed, judging by this statement.

------
soc88
Yet another Dart post making no sense at all.

