1

If we look at the definition of "dynamically-typed programming languages" in Wikipedia, it says:

Programming languages which include dynamic type-checking but not static type-checking are often called "dynamically-typed programming languages".

and

Dynamic type-checking is the process of verifying the type safety of a program at runtime. Implementations of dynamically type-checked languages generally associate each runtime object with a "type tag" (i.e., a reference to a type) containing its type information. This runtime type information (RTTI) can also be used to implement dynamic dispatch, late binding, downcasting, reflection, and similar features.

But the thing is, when using Ruby and JavaScript, I never see the type being "checked".

In a video I watched before, the author said that static typed just means a variable's type is defined / declared and compiled, and cannot change, while dynamic typed means a variable's type can change any time when the program is running, and I see it describing static / dynamic typed quite clearly and simply.

Actually, according to GoF, a type is simply a set of interface, so how can you "check" the type, other than whether it responds to a particular message? That is, when using dynamically typed languages, I don't really see it "checked" as in "Dynamic type-checking". Does or when does the checking happen?

2
  • It's pretty hard to imagine a *non-*type-checked language... I guess one where operations have types, rather than values having types? E.g. in assembly you will have no problem multiplying two pointers together, using the integer multiply instruction.
    – user253751
    Jan 10, 2016 at 3:29
  • 2
    I'll just add a plug for my favorite essay on this subject: Chris Smith's What to know before debating type systems. Jan 10, 2016 at 6:14

3 Answers 3

12

Javascript:

>>> 1()
TypeError: 1 is not a function

Ruby:

>>> 1 + ""
String can't be coerced into Fixnum

These are both simple cases of dynamic type error. Many languages, including almost all dynamic languages but also, e.g., C# and Java, do "type tagging". That is, the runtimes of these environments must, in effect, attach a representation of a type to every object. This is different than static typing because type tags exist at runtime and in at least the dynamic, imperative languages like Ruby and Javascript one variable may point to different objects with different types.

The runtime must, to implement the semantics of the language, check these type tags all the time. For instance, in performing the + operation on two objects, these languages check the type tags on both objects to decide what to do. If both objects are tagged as numeric, then addition is performed (possibly after some type conversion to a common numeric type). If both objects are tagged as string type-tags, then string concatenation is performed. (What may have tripped you up is that Javascript will perform extensive amounts of runtime-type conversions in normal operation. This makes it seem like it is not checking type-tags, because no type errors are thrown, when in fact type-tags are being checked all over the place to perform these conversions.)

Note that this type-tag checking bears only a vague and mostly misleading resemblance to (static) type checking. Static type checking checks properties of the expression before run time while type-tag checking checks properties of the value the expression expresses at run time. Both Ruby and Javascript perform type-tag checking in their basic runtime environment (e.g. in +, -, function invocation). They also allow the user of the language to perform type-tag introspection. That is, they allow the user to check the type-tag of a value at runtime.

Actually, according to GoF, a type is simply a set of interface, so how can you "check" the type, other than whether it responds to a particular message?

I am not familiar with this definition, but it strikes me as misleading. A static type is a token that gets associated according to a set of typing rules with expressions in a language and is used to define which expressions are semantically valid in that language. A "dynamic type" (or type-tag, as I prefer) is a value that gets associated with objects in a language's runtime. In some sense, both are tied to interfaces. In statically typed languages, the type defines what expressions an expression of that type may legally appear in and so to that extent determines an interface for that type. Vaguely similarly, type-tags determine, in part, which operations will end in a runtime "TypeError" before the operation is even attempted.

However, it is misleading to identify the type/type-tag with its interface in most static-dynamic languages. Essentially all static and dynamic languages are largely nomatively and not structurally typed. That is, in a normal statically typed language, if you define a type YourCustomer and I define MyCustomer, expressions of the two types will not be interchangeable. even if the definitions of YourCustomer and MyCustomer are identical up to naming. Similarly, if you define a Javascript object with type-tag YourJSCustomer and I define a Javascript object with type-tag MyJSCustomer, even if these two objects have all the same properties and methods otherwise they will not be interchangeable in the face of type-tag introspection.

It is true that in many dynamically typed languages, type-tag introspection is not always used and so YourJSCustomer and MyJSCustomer will be interchangeable in many environments. This is because these languages allow replacing or supplementing type-tag checking with attribute-checking. So if you call x.foo() in JS, Ruby, Python, &c., it will look for the .foo attribute on the object x. This allows the elimination of some, but typically not all, type-tag checking.

Note that in statically typed languages with structural typing, you can have YourCustomer and MyCustomer interchangeable in most/all contexts. This gives a language feel much closer to a language like Javascript or Ruby. I would suggest looking at TypeScript for this, which adds a type system to Javascript.

2
  • 1
    Re GoF: I think OP may have been thinking of "type" in the mathematical or Liskov sense of the term: A type is a set of behaviors and functional requirements. You see this in type theory, where there may not even be a specific "language" to speak of.
    – Kevin
    Jan 10, 2016 at 5:38
  • @Kevin are you saying this "type" is different from that "type"? That is, the "type" in OOP, vs "type" in general, meaning the "type" as in static type and dynamic type Jan 10, 2016 at 12:31
4

When we describe a language as type-checked, we mean that the language won't let you perform operations invalid for the type. Neither statically nor dynamically typed languages will let you multiply strings together, call a number in the place of a function, etc. A language without type checking would let you do all of those things without complaint.

Whether you do this by checking all the types at compile time, by checking the types at runtime, or seeing if an object responds to a message is an implementation detail of each language. All of those techniques fall under the rubric of type checking.

0

According to Eric Lippert a Type is

... an abstract quantity that we can manipulate using rules. Like "if T is a type then T[] is also a type", and so on.

The implementation of how a language compiler or runtime implements Types is another thing. In a compiled language, like C or C# or Java, this checking happens at compile time, and in Java and C# these checks also happen at runtime. However, in javascript and Ruby, these checks happen (to my knowledge) exclusively at runtime since no compilation is required.

so how can you "check" the type, other than whether it responds to a particular message?

Dynamic languages deal with types on every single expression that it evaluates because the runtime needs to know the types of the objects that it's interpreting in order to know what to do at all!

In the other good answers here, some examples of badly formed expressions are given, but some other examples also exist. Think of the difference between == and === in javascript for example.

console.log('5' == 5)  // true
console.log('5' === 5) // false

The javascript runtime needs to check the type of the objects at runtime in order to obey its specification.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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