Naming of Dynamic#invokeDynamic Method

536 views
Skip to first unread message

Daniel Spiewak

unread,
Jan 26, 2011, 5:16:22 PM1/26/11
to Scala Language
After some discussion, it seems to me that the (newly renamed) invokeDynamic method on the Dynamic trait should actually be named a bit more in line with what it's doing.  As Charles Nutter points out, it's not really true dynamic dispatch, it's really just an intercept for method failure.  In fact, it's exactly what method_missing does in Ruby and doesNotUnderstand in Smalltalk.  So in other words, there are a few languages out there that already have a feature very much like this one.  And while there is no standard for the naming, the convention is to imply the catching of an unhandled message.  This is not at all what "invokeDynamic" implies (particularly in light of JSR-292 and the potential confusion there).

I propose that we rename invokeDynamic (again) to something slightly more indicative of what it is doing.  I'm a Ruby guy, so methodMissing strongly appeals to me, but I would be ok with almost anything which hints at what is really going on (rather than implying something that it is not).

Daniel

Charles Oliver Nutter

unread,
Jan 26, 2011, 5:27:45 PM1/26/11
to scala-language
On Jan 26, 4:16 pm, Daniel Spiewak <djspie...@gmail.com> wrote:
> I propose that we rename invokeDynamic (again) to something slightly more
> indicative of what it is doing.  I'm a Ruby guy, so methodMissing strongly
> appeals to me, but I would be ok with almost anything which hints at what is
> really going on (rather than implying something that it is not).

There's another precedent in Groovy, which calls the same feature
missingMethod (I suggested they add methodMissing some years
ago...they did, but I'm unsure why they reversed the word order).

The confusion with "real" dynamic invocation and JSR-292 concerns me
as well. To me, dynamic invocation does not require that the target
object implement specific behavior in order to participate.
methodMissing does, specifically to support callee-driven symbolic
invocation.

Another example why this isn't "real" dynamic invocation is from C#.
In C#, the "dynamic" type is used not for callee-driven symbolic
invocation, but as a hook into the Dynamic Language Runtime, which can
handle any arbitrary object/type. In some cases, the objects
themselves do implement basic lookup and optimization mechanisms to
aid dynamic invocation, as with IronPython and IronRuby. But that's
not a prerequisite for "dynamic" invocation, and the DLR will happily
route dynamic calls from one static type to another static type
without either of them implementing any special logic.

- Charlie

Daniel Sobral

unread,
Jan 26, 2011, 5:33:58 PM1/26/11
to scala-l...@googlegroups.com
method_missing? missingMethod sounds so much better to my ears...

Groovy uses methodMissing and propertyMissing (oh, just read Nutter's reply! they use missingMethod now!), the latter being unneeded in Scala. It's camel case, in line with the more popular Ruby use, so I'm all for it, if it truly does the same thing. If it does something _similar_, however, I'm very much against using that name.

Here's a couple of relevant posts about similar functionalities in various languages:

--
Daniel C. Sobral

I travel to the future all the time.

martin odersky

unread,
Jan 27, 2011, 3:10:45 AM1/27/11
to scala-l...@googlegroups.com
On Wed, Jan 26, 2011 at 11:16 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
After some discussion, it seems to me that the (newly renamed) invokeDynamic method on the Dynamic trait should actually be named a bit more in line with what it's doing.  As Charles Nutter points out, it's not really true dynamic dispatch, it's really just an intercept for method failure.  In fact, it's exactly what method_missing does in Ruby and doesNotUnderstand in Smalltalk.  So in other words, there are a few languages out there that already have a feature very much like this one.  And while there is no standard for the naming, the convention is to imply the catching of an unhandled message.  This is not at all what "invokeDynamic" implies (particularly in light of JSR-292 and the potential confusion there).

It's an interesting proposal. It seems the terminology depends very much on your setup/viewpoint. Using type Dynamic it's possible to write a DynamicProxy that can call every Java object dynamically. On JDK7, the invokeDynamic method would be implemented with a invokeDynamic instruction, so in that sense the method name is right on spot. On the other hand, a DSL would implement invokeDynamic with something different.

But really, my primary focus for that feature is integration of dynamic languages, not so much DSLs. These dynamic languages usually have their own implementation of missingMethod that gets invoked when the first-line dynamic dispatch fails. So calling first-line dynamic dispatch also missingMethod would be very confusing.

I agree that calling the method invokeDynamic might suggest too strongly that this is always the same as the instruction. On the other hand, I want to keep dynamic in the name, also because the method lives in the Dynamic trait. So I think we could rename to `applyDynamic'. What do you think about that?

Cheers

 -- Martin

----------------------------------------------
Martin Odersky
Prof., EPFL and CEO, Scala Solutions
PSED, 1015 Lausanne, Switzerland


Daniel Spiewak

unread,
Jan 27, 2011, 10:41:20 AM1/27/11
to scala-l...@googlegroups.com
Given that the method lives in the Dynamic trait, why do we need Dynamic in the name?  That sounds really redundant.  Sort of like using "mapIterator" instead of "map" in the Iterator trait.

In any case, I question whether invokedynamic (the instruction) would actually be a useful implementation given the semantics of Dynamic with respect to Scala.  I'm assuming you would be generating CallSite(s), well, at the call site.  Thus, invokedynamic would transparently replace invocations of Dynamic#invokeDynamic.  This strategy would not only rule out DSLs, but it would also be completely useless in the face of languages like JRuby (which doesn't have methods which peer directly to JVM methods).  I'm hoping that I misunderstood what you meant by "implemented with an invokedynamic instruction".

All that aside, I'm not sure I agree with the analogy of invokeDynamic as the "first line" dispatch for any given dynamic language.  For starters, we're not *in* any given dynamic language; we're in Scala.  As such, we can't be working with the "first line" anything for any language accept Scala.  In general, I think it might be more productive to think of Dynamic in terms of a fallback dispatch for Scala, one which makes it possible to write compatibility layers for dynamic languages.  And there will need to be compatibility layers, since dynamic languages like JRuby have complicated dispatch semantics.

If we look at Dynamic from a Scala perspective, then the "fallback" concept seems substantially more natural from a naming perspective.  Basically, it comes down to a question of precedence: if type A <: Dynamic and defines identifier foo, then some code accesses foo on type A, does that code use Dynamic to get at foo, or is it a conventional statically-determined dispatch?  If the former (ie Dynamic has precedence), then invoke makes some sense as a name.  However, if the latter, then the semantics are precisely the same as method_missing and should be named accordingly.

I guess my perspective boils down to the fact that we're designing a language feature for *Scala*, so that feature should be named in a way which reflects what that feature does from *Scala's* point of view.  Other languages are secondary.  And, by following this design guideline (Scala first for Scala features), the interop layers for other languages will be easier and more natural to design.

Daniel

Charles Oliver Nutter

unread,
Jan 28, 2011, 4:43:43 PM1/28/11
to scala-language
On Jan 27, 2:10 am, martin odersky <martin.oder...@epfl.ch> wrote:
> your setup/viewpoint. Using type Dynamic it's possible to write a
> DynamicProxy that can call every Java object dynamically. On JDK7, the
> invokeDynamic method would be implemented with a invokeDynamic instruction,
> so in that sense the method name is right on spot. On the other hand, a DSL
> would implement invokeDynamic with something different.

You're still not doing a dynamic invocation at the call site, you're
doing a static invocation of a specific method name with a symbol and
a set of arguments. Whether the resulting target object/proxy
eventually does its own "real" dynamic invocation or not is beside the
point. Because of that I find the invokeDynamic name misleading. It's
invokeByName at best.

There's also the optimization aspect of this; since this isn't really
doing a dynamic invocation, it has to bounce through someone else's
implementation of invokeDynamic. If the same invokeDynamic is used by
multiple consumers, as in your DynamicProxy example, only the body of
DynamicProxy will inline on current JVMs (and not the eventual dynamic
call, however it's implemented). If instead invoking against your
dynamic type were actually a dynamic invocation, the resulting target
could be inlined all the way back.

Yes, this is a limitation of current JVMs. But it's a big one. See
Cliff Click's presentation from JVMLS a few years ago where he pointed
out this bouncing through a general piece of code was a primary reason
JRuby did not optimize as well as it could on their JVM. If Azul's VM
couldn't optimize it, it's probably going to be a while before any
generally-available JVM can optimize it.

> But really, my primary focus for that feature is integration of dynamic
> languages, not so much DSLs. These dynamic languages usually have their own
> implementation of missingMethod that gets invoked when the first-line
> dynamic dispatch fails. So calling first-line dynamic dispatch also
> missingMethod would be very confusing.

If you really want to get a tight integration of dynamic languages,
then a simple "by name" invocation is insufficient. You either want to
actually invokedynamic at the bytecode level, letting the target
language figure out how to wire up the dispatch, or you need to ask
the target language for some sort of method handle you then implement
in-place, which will allow it to inline properly.

I appreciate making dynlang integration better, but calling the target
method invokeDynamic is very misleading, since it isn't "invoke
dynamic".

> I agree that calling the method invokeDynamic might suggest too strongly
> that this is always the same as the instruction. On the other hand, I want
> to keep dynamic in the name, also because the method lives in the Dynamic
> trait. So I think we could rename to `applyDynamic'. What do you think about
> that?

How about invokeSymbolic? Then it's clear this isn't doing a dynamic
invocation but a symbolic one. It's also far less likely to conflict
with any existing libraries/languages that might have "invokeDynamic"
as a method already (as JRuby does in some places).

- Charlie

martin odersky

unread,
Jan 28, 2011, 5:00:31 PM1/28/11
to scala-l...@googlegroups.com
Hi Charles,

You're still not doing a dynamic invocation at the call site, you're
doing a static invocation of a specific method name with a symbol and
a set of arguments. Whether the resulting target object/proxy
eventually does its own "real" dynamic invocation or not is beside the
point. Because of that I find the invokeDynamic name misleading. It's
invokeByName at best.

Essentially it boils down to question whether I can do a direct call or need a proxy. For me, that's an implementation detail.

Or wrap in proxies, yes. Ideally, the dynamic language we interact with implements Scala's Dynamic type. As long as that does not happen we need to go though proxies.
 
I appreciate making dynlang integration better, but calling the target
method invokeDynamic is very misleading, since it isn't "invoke
dynamic".

> I agree that calling the method invokeDynamic might suggest too strongly
> that this is always the same as the instruction. On the other hand, I want
> to keep dynamic in the name, also because the method lives in the Dynamic
> trait. So I think we could rename to `applyDynamic'. What do you think about
> that?

How about invokeSymbolic? Then it's clear this isn't doing a dynamic
invocation but a symbolic one. It's also far less likely to conflict
with any existing libraries/languages that might have "invokeDynamic"
as a method already (as JRuby does in some places).

 
Pardon me for coming from a hopelessly static corner of the world, but I don't understand most of the terminology. What's the difference between invokeDynamic and invokeSymbolic and invokeByName?

For me, invokeDynamic/applyDynamic is an invocation of a method where I do not know the precise method signature (or: on the implementation level: vtable entry), nor do I know whether that specific method is actually implemented on the receiver.

Cheers

 -- Martin 

Daniel Spiewak

unread,
Jan 28, 2011, 5:05:45 PM1/28/11
to scala-l...@googlegroups.com
How about invokeSymbolic? Then it's clear this isn't doing a dynamic
invocation but a symbolic one. It's also far less likely to conflict
with any existing libraries/languages that might have "invokeDynamic"
as a method already (as JRuby does in some places).

I could get behind invokeSymbolic.  It's certainly more accurate than invokeDynamic.  However, I keep getting stuck on the fact that this is a fallback dispatch mechanism from Scala's perspective.  Even if the primary purpose is dynlang integration, the feature design needs to be focused on Scala.  Again, while it may be the first-line dispatch when calling into the dynlang, it's still the second-line dispatch when making a Scala call.


For me, invokeDynamic/applyDynamic is an invocation of a method where I do not know the precise method signature (or: on the implementation level: vtable entry), nor do I know whether that specific method is actually implemented on the receiver.

If we were calling that method directly, then yes, I could sort of see your point.  However, the Dynamic API is not directly exposed to the call site.  It's only an artifact of the receiver, which can then choose to handle it in whatever way is required (a way which may in fact be static, not dynamic).  So, thinking from an API consumer's perspective (and remember, the API consumer here is the one implementing the method in Dynamic), the "Dynamic" part of the method name doesn't really make any sense.

Daniel

Charles Oliver Nutter

unread,
Jan 28, 2011, 5:22:07 PM1/28/11
to scala-language
On Jan 28, 4:00 pm, martin odersky <martin.oder...@epfl.ch> wrote:
> need a proxy. For me, that's an implementation detail.

For you it is :) For any target object that wants to enlist in the
protocol, it's definitely an important detail that can't just be
brushed under the covers.

> Or wrap in proxies, yes. Ideally, the dynamic language we interact with
>
> implements Scala's Dynamic type. As long as that does not happen we need to
> go though proxies.

It will be almost impossible for most languages to do this without
yanking in a Scala dependency for all users all the time. Perhaps this
should be spun off into a common library without any language-specific
dependencies?

> Pardon me for coming from a hopelessly static corner of the world, but I
> don't understand most of the terminology. What's the difference between
> invokeDynamic and invokeSymbolic and invokeByName?
>
> For me, invokeDynamic/applyDynamic is an invocation of a method where I do
> not know the precise method signature (or: on the implementation level:
> vtable entry), nor do I know whether that specific method is actually
> implemented on the receiver.

And I'm coming from a dynamic-language-implementer's corner of the
world. :) I'll try to explain my thoughts better.

I'm primarily concerned about calling it invokeDynamic since that will
be confusing to anyone familiar with the invokedynamic bytecode and
JSR-292 work. So there's that.

My somewhat weak secondary justification is the fact that it's not
actually doing a dynamic invocation, since it requires additional
plumbing to do that invocation. In Ruby, dynamic invocation is just
how invocation is always done, so it's not necessary that anyone
implement a specific method or implicit DynamicProxy. It's handled by
the language runtime...and so we say Ruby dispatches dynamically. With
Scala's "invokeDynamic", you can't simply start using it today on any
existing object or type. Someone has to make a proxy that knows how to
do the dispatch for you, or the target object needs to implement a new
interface. The dynamic part of the dispatch is not intrinsic to the
language, not handled for you by the runtime (or compiler). You have
to do extra. All you get is dynamic-looking sugar over the static
part.

Does that make sense?

- Charlie

Jason Zaugg

unread,
Jan 28, 2011, 5:25:23 PM1/28/11
to scala-l...@googlegroups.com
On Fri, Jan 28, 2011 at 11:00 PM, martin odersky <martin....@epfl.ch> wrote:
> For me, invokeDynamic/applyDynamic is an invocation of a method where I do
> not know the precise method signature (or: on the implementation level:
> vtable entry), nor do I know whether that specific method is actually
> implemented on the receiver.

I think invokeDynamic would be a reasonable name for this, were it not
already associated with the existing JSR. If you make a conscious
decision to move away from that, applyDynamic seems reasonable to me,
given the existing use of 'apply'.

I would also like folks to consider what other features of regular
Scala function application might be brought to dynamic invocations.

These seem useful, perhaps on a opt-in basis:

- argument names
- by-name evaluation
- return type other than Dynamic

Marginally useful:

- type arguments (converted to manifests?)
- sequence arguments

-jason

martin odersky

unread,
Jan 29, 2011, 5:13:32 AM1/29/11
to scala-l...@googlegroups.com
On Fri, Jan 28, 2011 at 11:05 PM, Daniel Spiewak <djsp...@gmail.com> wrote:

How about invokeSymbolic? Then it's clear this isn't doing a dynamic
invocation but a symbolic one. It's also far less likely to conflict
with any existing libraries/languages that might have "invokeDynamic"
as a method already (as JRuby does in some places).

I could get behind invokeSymbolic.  It's certainly more accurate than invokeDynamic.  However, I keep getting stuck on the fact that this is a fallback dispatch mechanism from Scala's perspective.  Even if the primary purpose is dynlang integration, the feature design needs to be focused on Scala.  Again, while it may be the first-line dispatch when calling into the dynlang, it's still the second-line dispatch when making a Scala call.

But you need to see both the dynamic and static perspective. It's perfectly possible that an object that has a certain method, say, "foo", has static type "Dynamic". So statically, "foo" is invisible, but it is still present. That's why I believe that "missingMethod" is confusing. The method is not  missing at all, it's just invisible for the static typechecker. If you want a painfully long name you could pick "methodStaticallyInvisibleNowTryAppliyDynamic", but  I believe we all prefer "applyDynamic" over that.

Cheers

 -- Martin



 
For me, invokeDynamic/applyDynamic is an invocation of a method where I do not know the precise method signature (or: on the implementation level: vtable entry), nor do I know whether that specific method is actually implemented on the receiver.

If we were calling that method directly, then yes, I could sort of see your point.  However, the Dynamic API is not directly exposed to the call site.  It's only an artifact of the receiver, which can then choose to handle it in whatever way is required (a way which may in fact be static, not dynamic).  So, thinking from an API consumer's perspective (and remember, the API consumer here is the one implementing the method in Dynamic), the "Dynamic" part of the method name doesn't really make any sense.

Daniel



--

Josh Suereth

unread,
Jan 29, 2011, 7:52:49 AM1/29/11
to scala-l...@googlegroups.com
On Fri, Jan 28, 2011 at 5:22 PM, Charles Oliver Nutter <hea...@headius.com> wrote:
On Jan 28, 4:00 pm, martin odersky <martin.oder...@epfl.ch> wrote:
<snip/>

> Or wrap in proxies, yes. Ideally, the dynamic language we interact with
>
> implements Scala's Dynamic type. As long as that does not happen we need to
> go though proxies.

It will be almost impossible for most languages to do this without
yanking in a Scala dependency for all users all the time. Perhaps this
should be spun off into a common library without any language-specific
dependencies?

<snip/>

I think this is a huge point that we shouldn't miss.  If we want to interop with dyn languages on the JVM, the 'core' library should consist of a single/set of standalone interface(s) that dyn languages can pull in as a separate JAR dependency.  This dependency could be small and simple and gives us a decent migration strategy where the dyn-lang interface wouldn't be easily broken by new scala-libraries.

Daniel Spiewak

unread,
Jan 30, 2011, 11:25:53 PM1/30/11
to scala-l...@googlegroups.com

I think this is a huge point that we shouldn't miss.  If we want to interop with dyn languages on the JVM, the 'core' library should consist of a single/set of standalone interface(s) that dyn languages can pull in as a separate JAR dependency.  This dependency could be small and simple and gives us a decent migration strategy where the dyn-lang interface wouldn't be easily broken by new scala-libraries.

I was talking with Charlie about this offline, and I think the solution to this problem is an implicit conversion on the Scala side, probably in a small compatibility layer offered (but not necessarily shipped with) the dynlang in question.  For example, in the case of JRuby, we would need a conversion from RubyObject to Dynamic, and that would solve the whole problem.  JRuby wouldn't be saddled with a static dependency on a class in the Scala core (or even in an outlier library) and Scala code wouldn't have any troubles dealing with the implicit proxy.

Daniel

Daniel Spiewak

unread,
Jan 30, 2011, 11:44:04 PM1/30/11
to scala-l...@googlegroups.com
But you need to see both the dynamic and static perspective. It's perfectly possible that an object that has a certain method, say, "foo", has static type "Dynamic". So statically, "foo" is invisible, but it is still present. That's why I believe that "missingMethod" is confusing. The method is not  missing at all, it's just invisible for the static typechecker. If you want a painfully long name you could pick "methodStaticallyInvisibleNowTryAppliyDynamic", but  I believe we all prefer "applyDynamic" over that.

Ok, I see your point re: missingMethod.  I an also see why you like the "Dynamic" suffix.  Coming at it from the a type systems perspective, the name does make sense.  However, I think the terminology needs to be weighed against the fact that most people aren't coming at this from a type systems perspective.  I mean, I've put in quite a bit of time in that magical land of type theory, and you still had to point out how the name is justified!

I think the reason I didn't (and I suspect others won't) see the logic in the "Dynamic" suffix is we connect notion of "dynamic dispatch" with the typeless message send of languages in the Smalltalk family.  As Charlie has pointed out, Dynamic is a bit different from this, partially owing to the extra leg-work involved on the receiver side, and partially because of the fact that it is a last-ditch fallback mechanism for the name binding.  A more formal way to think of this would be to see Smalltalk-style dispatch as runtime name binding, while Dynamic still involves compile-time name binding (though the final resolution happens explicitly at runtime on the receiver side).  The distinction isn't a large one, but it is enough that I think it will confuse those of us more accustomed to the dynlang interpretation of "dynamic".

With that said, "invokeSymbolic" and "invokeByName" aren't totally accurate either, since they almost imply a "DynamicProxy" default case, leading to the impression that Dynamic is Scala's long-awaited reflection library.  I still think that "invokeSymbolic" is probably less confusing that "invokeDynamic", but it's certainly not without flaws.

Daniel

Heiko Seeberger

unread,
Feb 1, 2011, 2:53:47 PM2/1/11
to scala-language


> That's why I believe that "missingMethod" is confusing. The method is not
> missing at all, it's just invisible for the static typechecker. If you want
> a painfully long name you could pick
> "methodStaticallyInvisibleNowTryAppliyDynamic", but  I believe we all prefer
> "applyDynamic" over that.

I like applyDynamic and some of the other suggestions. In any case
invokeDynamic is really bad, because it causes lots of confusion.
Please change it.

Heiko

Michael Stal

unread,
Feb 1, 2011, 5:07:53 PM2/1/11
to scala-language

I agree with Heiko. invokeDynamic would lead to a wrong illusion. applyDynamic would make much more sense

- Michael




Reply all
Reply to author
Forward
0 new messages