|
That statement I made is definitely true. I'm not arguing for or against Java, I'm arguing that both the hypothesis and the conclusion and everything about that article is flawed (it basically screams LINK-BAIT). Continuations are a good example
First of all, most implementations for continuations that are in common use are on top of virtual machines that are stack-based, so providing first-class continuations is a bitch, because you've got no way out of it other than to save the classical call-stack somewhere and restore it later, should you need to. And because of the way the call-stack is implemented, saving / restoring it is both time and space consuming.This was a pragmatic decision, more often than not, because explicit support is really not that useful, while being error-prone and because the major use-cases, like exceptions handling, coroutines, asynchronous tasks, etc... can receive language support that's also optimal on top of a stack-based VMs. And in most cases you don't need the unlimited extent that continuations on top of Scheme provide (most people just need the "async" support like it was done in C#, which is just compiler-related syntactic sugar). Some people even consider continuations "harmful" as sort of a modern Goto (a topic on which I have no opinion btw). However, if you get rid of the traditional call-stack and make all methods receive an implicit continuation of the caller, and overload the "return" operator to call that implicit continuation (basically making everything CPS), then you could optimize this more efficiently. By how much, nobody knows yet, because there have been only weak attempts at solving this (I only know of Parrot, the new Perl 6 VM, but it hasn't done anything spectacular yet). Also remember that our current commodity, general-purpose hardware is optimized primarily for C, which assumes a traditional call-stack. And you can always design hardware that's optimized for different things. Dynamic typing ... Clojure has this problem and that's
why they added type-hints
You haven't actually mentioned the exact problem Clojure is having. Clojure added type-hints mostly to avoid primitive boxing/unboxing. It doesn't have much to do with "dynamic typing".In case you weren't aware, the JVM bytecode is pretty dynamic. Besides primitive operations on primitives, which have special bytecode instructions, the only place where you really, really need the name of a class or interface is when calling a method. And so the name of the Class.method ends up hardcoded in the bytecode, but that's only because Java itself has clear rules for method-lookup, so providing the means to override that method-lookup was unnecessary. However in Java 7 they added invoke_dynamic, which does provide the means of overriding the method-lookup being done. JVM engineers, like John Rose, promised the same performance characteristics as invoke_virtual. But Clojure doesn't even need invokeDynamic most of the time, because in most cases method calls in Clojure are only polymorphic and not dynamic. And because most things in Clojure are immutable. JRuby would have been a better example. EDIT: formatting (moved ending paragraph to the beginning) |