16

Being either static or dynamic should be something completely supported in the language. Static vs dynamic shouldn't be something that you have to turn on and off, switching between basically 2 languages.

I'm talking full blown mixed typing madness like this thing:

class MyClass {
  function myMethod(x: int, y: int){        # one parameter is typed, the other not
    return <cast_to_int> y.return_integer(x); #casting to guarantee the contract
  }    
}

MyClass static_obj = MyClass();  #statically typed instantiation;
var dynamic_obj = {};   #dynamically typed instantiation
dynamic_obj.return_integer = (function (x) {return x*2}) #dynamic method creation

static_obj.myMethod(3, dynamic_obj)     # This returns 6

dynamic_obj.return_integer = (function (x) {return x+1}); # dynamic member reassignment

static_obj.myMythod(3, dynamic_obj)   # this returns 4


static_obj.myMethod('asdf', dynamic_obj) # This can't compile, because of typing

# and also this crazy thing; Notice that the static interface of the method is respected
if (<user input> == 2){
    static_obj.myMethod = (function (x: int, y){return x + y.yet_some_other_method(x);})
}

# but when the static contract is not respected, it doesn't compile
static_obj.myMethod = (function (a, b, c) {return 'asdf'}) # Compile time error

I'm interested in this topic because I really like that API discoverability in static languages is great (thing i liked about Java, C# and ABAP for a while), but I also like testing stuff at run time, monkey patching, REPLs, reassignment, and crazy reflection magic (which I liked about JavaScript and Python).

I'm aware of Dart's static type checker, but that's not enough, because it provides no actual static guarantees.

I'm also not interested in type inferrence. I want true static running next to true dynamic behavior. I also am aware that I can use mapping types like python's dict, or any JS object, or Java's HashMap) to pass around data (or even functions), but Java's mappings can't carry methods in them, Python's dicts can't (out of the box) have methods in them, and even though JS simply laughs at any kind of static restrictions - adding methods at runtime that DO get access via the this keyword to the context object is something really cool (I know Python does it too, when adding functions on the class object, but NOT on class instances).

My curiosity was also sparked by this paper: Static typing where possible, dynamic typing where needed

And the API discoverability argument came from my own experience, but this paper seems to support it: http://personales.dcc.uchile.cl/~rrobbes/p/ICPC2014-idetypes.pdf

6

4 Answers 4

30

Yes. C# as of 4.0 is probably the most common example, with the dynamic keyword. There are likely other good examples that I am forgetting or don't know about.

0
9

A great example of this is Dylan. You can use static and dynamic typing in Dylan, e.g.,

define method double(a :: <integer>) => (result :: <integer>)
    2 * a
end

or

define method double(a) => (result)
    2 * a
end

This extends to variables, etc. Another more mild example is REBOL, but only in its function definitions, e.g.,

double: func [a [integer!]] [a * 2]
double: func [a] [a * 2]

Function parameters are the only place in REBOL any kind of type checking (or declaration, for that matter) is permitted.

3

Classic Visual Basic and VBA has had this ability from day one.

VB.NET also had this ability from release (1.0) with the option to "switch it off" using Option Strict On statement at the top of the code file or project wide in the project properties. This doesn't actually switch it off as such it just won't compile a late binding statement when this is on.

C# eventually caught up some time later in version 4.0 with the difference that you have to "allow" it by using the dynamic keyword.

0

Java sort of has this with the Object class.

int myMethod(int x, Object y) {
  return x > 0 ? x : (int)y;
}

void go() {
  Object obj;
  if(Math.random() > 0.5)
    obj = 3;
  else
    obj = "hello";
  myMethod(-5, obj); // throws ClassCastException if obj is a String
}

In Java 8, lambda functions are introduced, so you can put functions inside maps, though it's a bit unwieldy:

Map myObj = new HashMap();
myObj.put("add",
          (BiFunction) (Object x, Object y) -> ((Number) x).intValue() + ((Number) y).intValue());
BiFunction addition = (BiFunction) myObj.get("add");
int apply = (int) (Number) addition.apply(3, 2.2);
7
  • 7
    Technically, Autoboxing and Unboxing is not the same as dynamic typing.
    – Alexander
    Commented Dec 22, 2014 at 3:07
  • 1
    @Alexander True, hence the "sort of".
    – Ypnypn
    Commented Dec 22, 2014 at 3:10
  • 7
    What makes this different from dynamic typing is that Java doesn't let you access a method or field that it doesn't know about at compile time. You can't say Object o = foo; o.xyz(); because Object does not have a method called xyz. If you do that in a language like VB the code will wait until runtime to see if there's an xyz method.
    – Gabe
    Commented Dec 22, 2014 at 4:57
  • java sort of has some reflection API. but that's hardly what i would call dynamic. And i don't know if you can do assignment at runtime on unknown properties... basically what i showed in my example was something that any language that uses some eval could do... in java that's waaay complicated to achieve Commented Dec 22, 2014 at 14:10
  • @Gabe You can cast the object to the type you think it is, which is more or less what a dynamically-typed language does under the hood anyways to make sure you don't get undefined behavior. Although this is orthogonal to the question, you can implement duck typing with reflection or by passing around Map<String, Object> (which is, again, pretty much the same thing e.g. Python does).
    – Doval
    Commented Dec 22, 2014 at 16:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.