6 ms·
Thanks for the amazingly detailed response! I'm still unclear about one thing: Couldn't you simply throw an exception if the type annotation did not match your
by tlack 14y ago
Thanks for the amazingly detailed response! I'm still unclear about one thing:
Couldn't you simply throw an exception if the type annotation did not match your usage of it? For instance:
/* v8-type: string, string -> string */
function append_strings(a, b) {
return a*b; /* exception */
}
Similarly, the underlying library could gradually get type annotations, as Erlang has been doing progressively for the past year or two. As more and more code gets annotated, you can "lift" that knowledge into any code that calls, for instance, String.substr(), and assert that the types match when they are provided.
To me it seems that even the complications caused by multiple types of arguments to many built-in functions would be less complex to resolve at runtime than the hairy, "lazy" logic they're referring to in this article.
Iterating through an array of type specs and resolving the correct underlying code (only in the specific case of annotated functions being invoked - usually 'hot path' code that has a simple breadth and call structure for other performance reasons), throwing an error if there's no match, seems easier than Hidden Classes, in my admittedly naive view.
- gliese1337 14y agoYou could, but then you'd have 'comments' that change the semantics of the program, which is exactly what comments are not supposed to do. The point of adding annotations in comments is that environments that don't understand the annotations will ignore them, because they're in comments. It's therefore only a not-horrible idea to add features via comments in situations where the new features actually don't change semantics, such that the program will still produce the same result when run in an environment that doesn't understand the extras.
- kevingadd 14y agoThat sort of explicit type annotation approach falls over for the more complex cases, like the function signature one I described. For example, let's say you have an object called a StringBuilder, like the one in Java/C#, and it's got a method for appending text to it. In JS, you'd use it like this: var bananaCount = 5; var sb = new StringBuilder(); sb.append("There are "); sb.append(bananaCount); sb.append(" bananas"); If you merely add type annotations, you're not going to win much here: /* v8-type: this(StringBuilder) (any) -> none */ sb.append = function (...) { ... }; If you go to the trouble of adding function overloading, maybe things get a little better - TypeScript does something like this hypothetical: sb.append = { /* v8-type: this(StringBuilder) (string) -> none */ function (...) { ... }, /* v8-type: this(StringBuilder) (number) -> none */ function (...) { ... } } OK, but now what if you've got collection types? If you create an instance of List, what type is List.items? It'd have to be any[], unless you also add something like generics. So now you have to add a generics system or you have to introduce type casts, just to avoid having all your type information polluted by 'any's. This may still be kind of unclear; it is often hard to see the failings of a type system until you see it in action on a larger application. In practice, it comes down to this: The type inferences that an engine like V8 or SpiderMonkey can draw at runtime end up being extremely accurate, and provide a lot more information than a compiler for a language like C or C# or Erlang has access to.