Re: New JVM instruction invokedynamic
On Sun, 14 Nov 2010 14:07:12 +0000, Tom Anderson wrote:
On Sun, 14 Nov 2010, Ken Wesson wrote:
On Sat, 13 Nov 2010 16:07:49 +0100, M.O.B. i L. wrote:
I read this article:
<http://java.sun.com/developer/technicalArticles/DynTypeLang/
index.html>.
It's about the new JVM instruction invokedynamic that should make
dynamic languages faster.
Remind me: what does invokedynamic do differently from invokevirtual?
Everything.
It's not just a slightly looser version of invokevirtual which lets you
be a bit more vague about types in the bytecode. It involves a
completely new, and frankly batshit insane, calling process, which
involves finding and using things called MethodHandles, which are
objects, but which can get involved with the call process.
Bear in mind that dynamic languages (here i will use a dynamic version
of java i have just made up) don't just need to be able to do:
var foo = 23;
foo.toString(); // foo has no static type here
They need to be able to do:
var foo = 23;
foo.toQuotedString = do String() {return "'" + this.toString() + "'"'};
// made-up lambda syntax foo.toQuotedString(); // that method didn't
even exist a minute ago
Supporting that inside the JVM requires some serious voodoo.
invokedynamic is it.
Funny. I don't think clojure uses invokedynamic if you do something like
(def my-thingie {:value 23})
....
(let [to-quoted-string #(str /' (% :value) /')]
(to-quoted-string my-thingie))
=> "'23'"
Mind you it's not attaching to-quoted-string to the object. Clojure has
multimethods and protocols but they have a kind of type hierarchy behind
them. Closest might be doing stuff like:
(defn call [name m & args]
(apply (m name) m args))
(def my-thingie {:value 23})
....
(def my-thingie
(assoc my-thingie :to-quoted-string #(str /' (% :value) /')))
(call :to-quoted-string my-thingie)
=> "'23'"
(def your-thingie {:value 42
:to-quoted-string #(str /" (% :value) /")}
(call :to-quoted-string your-thingie)
=> ""42"" ; you apparently prefer double quotes
Of course the syntax of the embedded closure is a bit awkward. Think of
the % as Java's "this" in this particular context.
One way to smarten it up with something like Java's lack of need for
explicit "this." on every member access would be to write a macro that
massaged (:keyword) (keywords cannot normally be called with zero args)
into, in essence, (% :keyword) wherever it occurred.
Calls could be chained of course:
(def your-thingie {:value 42
:doubled #(* 2 (% :value))
:double-string (str (call :doubled %))}