What prevents a statically typed language from having something like Ruby's method_missing?
Asked Answered
R

5

12

I don't have much experience with statically typed languages (currently learning Scala and loving it!) but one thing I've noticed is that they don't ever seem to have anything like Ruby's method_missing or ColdFusion's onMissingMethod. Is there some inherent limitation in statically typed languages that prevent or make this difficult?

Recreate answered 24/9, 2010 at 15:28 Comment(1)
For an example of a statically typed language that does have something like this built-in, take a look at opDispatch in D. opDispatch is a template method which is passed the method name and parameter types at compile time, so you can use metaprogramming to determine how to "run" the missing method. Of course, everything is still resolved statically by the compiler. Related SO question.Lemire
V
21

Certainly a mechanism for handling them could be added, but it is at odds with what static typing is: Compile-time determination that your program is free of type errors.

Addendum

Scala 2.9 introduced an experimental option enabling this sort of dynamic handling of accesses to types in ways that would otherwise fail static type checking. It was refined and made non-experimental in 2.10, though it is still controlled by a default-disable feature flag. You can read about it in the SIP 17 document. See SIP 18 for an explanation of Scala 2.10's "modularization" and feature flags.

Vaunt answered 24/9, 2010 at 15:48 Comment(3)
reflection APIs violate that as well, but they are present and highly used in most modern static languagesGilliangilliard
what Randall said is correct. For better or worse "historically" it's been a big divide for "compile time" versus not. That being said some newer languages come closer to bridging the gap (scala comes to mind, which I think has a REPL).Studner
@rogerdpack: Scala definitely has a REPL, though I don't think of it as an aspect of being "dynamic," just a huge convenience when working with the language.Vaunt
G
2

Scala version 2.9 introduces this functionality through the Dynamic trait (scaladoc). Classes that extend Dynamic get the magical method applyDynamic(methodName, args), which is analogous to Ruby's method_missing. As of Scala 2.9, the -Xexperimental option must be enabled to use Dynamic.

Grit answered 25/6, 2011 at 19:35 Comment(0)
M
1

In statically typed languages, member functions are invoked directly. If the compiler cannot figure out which member function to invoke, the program will not compile. Method invocation is, in this sense, static.

In dynamically typed languages, member functions are not invoked directly. Rather, calling code sends a message to an object, and then the language runtime figures out what to do with that message. For example, the runtime will scan the object for a method with the same name, and then will scan the object for a method with the name method_missing. Method invocation is, in this sense, dynamic.

C# 4 combines static typing with dynamic typing. An variable may have a compile-time type of dynamic. Any method invocations on this variable will be handled as in dynamically typed languages. Any method invocations on variables with static types will be handled as in statically typed languages.

# static invocation, bound at compile time by the compiler
var s = 6;
s.ToString();

# dynamic invocation, handled at runtime by the CLR
dynamic d = 6;
d.ToString();
Morman answered 24/9, 2010 at 16:1 Comment(2)
You're mixing up stuff. Dynamic dispatch exists in about every statically-typed OO language. And only some dynamically-typed languages use the message passing model as pioneered by Smalltalk. Python for example doesn't use message passing (instead, obj.method(args) translates into "get the function that the method member of obj points to, then call it with obj as first argument and args").Passionate
var has nothing to do with dynamic typing. It causes the compiler to infer the static type of the variable from the value assigned to it.Vaporescence
M
1

Just to further Randall's post, it is possible, but the reason it goes against the static paradigm is that it's beyond "dynamic dispatch". Dynamic dispatch happily lets you dispatch to a function that is dynamically bound to a known static piece of code. i.e. the compiler sets up the dispatch that is deterministically executed at runtime, from its perspective.

What the method_missing call does, is essentially make a "catch all" where you decide what to do based on the method name using a switch statement, or something equivalent (which I'm sure you know). Thus, the compiler has no idea what's going to happen here. Let's say the compiler did something like:

if (function is known at compile time)
{
  provide static call or dynamic call to "some" derivation
}
else
{
  bind the function call to obj.method_missing(...) and pass in the "details"
}

Then you have to provide method_missing like this:

def method_missing(intendedFunctionName, arguments)
{
  if (intendedFunctionName is "X")
  {
    X may not need arguments, so just do something
  }
  else if (intendedFunctionName is "Y")
  {
    Y expects 5 arguments of varying types
    Throw exception if there isn't the right number or types
  }
  ... etc ...
}

Asking the compiler to send you "arbitrary" (i.e. not known at compile time) arguments of arbitrary types, with an intendedFunctionName that you may not be accounting for... well, it's not very safe, and Scala is intended to be a statically safe language.

Yes, it's doable but not in the spirit of a static language. If you really want that type of flexibility, polyglot programming is probably your friend.

Note: Objective-C is not strictly statically typed. There is a runtime engine on which the code executes and the dynamic typing system does not allow code to be stripped or inlined like C/C++.

Mantelletta answered 27/9, 2010 at 14:29 Comment(1)
"Asking the compiler to send you "arbitrary" (i.e. not known at compile time) arguments of arbitrary types" and "not very safe" sound just like C varargs. :)Permute
T
0

Objective-C has "method_missing" (specifically, forwardInvocation and methodSignatureForSelector) and it is arguably statically typed. This works because it will treat static type errors as warnings rather than errors at compile time, since method dispatch occurs at runtime to a much greater extent than something like virtual methods in C++ (and this is why you can have "method_missing").

Tremain answered 27/9, 2010 at 14:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.