0

I am trying to understand static vs dynamic typing, but am really struggling to see how everything fits together.

It all starts with data types. As far as I understand, data types are quite abstract notions, which exist 'in' compilers in order to categorise data so that the operations on various types of data can be validated (i.e. in an attempt to stop you adding a string to an integer), and in order to generate the right machine code for the hardware interpretation of the value. I.e. say we have the following:

int myInt = 5;
char myChar = '5';

Console.WriteLine(myInt);
Console.WriteLine(myChar);

Both would ultimately write a five to the console window, but, since the representations in memory of integers and characters are different, the machine code which interprets the value in the memory location bound to the variable myInt, which takes that value and displays it on the console window, would be different to the machine code for myChar. Even though Console.WriteLine() 'does the same job', the different representations of five require different low level code.

So my question is this: if data types 'exist only in the compiler' - i.e. once the program has been compiled into machine code there is no knowledge of what type of data the value in a particular memory cell is (everything is just 1s and 0s) - then how can any type-checking be done at runtime? Surely there is no concept of data types at run time? So surely dynamic typing can't be anything to do with type-checking occurring at run time?

Where is my understanding going wrong, and could somebody please explain static and dynamic typing with respect to the argument given above? What is the big picture of what is going on?

I am trying to understand this for an essay, so references to books or online sources would be useful :) Thank you.

closed as too broad by Andres F., gnat, Scant Roger Nov 29 '15 at 6:51

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    Welcome to this site, Lord Cat. Your question seems way to broad for this site. I recommend you read the guidelines of what can be asked here; not any question is suitable here. For example, questions asking for books or references are (generally) off-topic. If you can imagine the answer to your question being one or more chapters of a book, or a even worse the subject of a course, then it's also off-topic here. – Andres F. Nov 28 '15 at 18:31
  • My suggestion is that you study type theory, and when you have a concrete question, then you can try asking it here. – Andres F. Nov 28 '15 at 18:32
  • 1
    I think this is a valid question, but it's obscured by some background noise. Please highlight what you're really asking. – JesseTG Nov 28 '15 at 18:43
  • Possible duplicate of What are the safety benefits of a type system? – gnat Nov 28 '15 at 18:48
  • @JesseTG I suppose, since you have clarified that type information is actually stored, how dynamic typing differs from static typing. Why would you ever need to do type checking at runtime? – Lord Cat Nov 28 '15 at 18:48
1

Your assertion that "datatypes exist only in the compiler" is not true for dynamic languages (and not a few static ones).

Once that doesn't hold, it becomes a simple runtime check.

  • Thanks for your answer! So why would you do runtime type checking at all? – Lord Cat Nov 28 '15 at 18:59
  • @LordCat - how would you dispatch otherwise when a variable's type can change at runtime? – Telastyn Nov 28 '15 at 19:01
  • But why would you want your variable's type to be able to change at runtime? Just for the purposes of space efficiency, so that you can reuse the same memory location? – Lord Cat Nov 28 '15 at 19:11
  • I believe from a type theory point of view, a dynamic language is a static language with only one type. The runtime check you're referring to is the same kind of check that occurs for sum types/tagged unions. All values of a sum type have the same type even though they hold different kinds of data. Essentially, in a dynamic language every value belongs to a single sum type. I'm basing this off of Practical Foundations For Programming Languages. I'm not sure how reflection factors into this view. – Doval Nov 28 '15 at 19:38
  • @LordCat: You would want the type to change if you have no idea at compile time what the type is. Say you download JSON data and read an item. That item could be an array, a dictionary, a string, a boolean, the null value, or a number (possibly an integer, possible a floating point or decimal number). Since you don't know that at compile time, how are you going to handle this? – gnasher729 Nov 28 '15 at 19:55
0

How can any type-checking be done at runtime? Surely there is no concept of data types at run time?

Sometimes there are data types at runtime. Other times, the type checking can be done entirely at compile-time. In principle, it's up to the implementation whether it chooses to implement a type check at compile time or at runtime, and they have a lot of options.

In languages like C++ and Java, there is a distinction between primitive types (typically integers, characters, etc) and structured or complex types (typically structs and classes). In these languages it's common for only the structured types to retain some metadata about their type at runtime (though that usually includes the types of their primitive members/fields). For example, in C++, the typeid function is typically evaluated at compile time, and works even on primitive types, while a dynamic_cast is executed at runtime and only works on classes.

In more dynamic languages like Python and Javascript, any variable can have any type, so a straightforward interpreter will most likely have to implement all variables as a "variant type", i.e. a class that literally carries its own type around with it. A more sophisticated interpretation may use optimizing AOT or JIT compilers that are run on sections of code where all typing issues can be proven at compile time, so it's safe to replace the variant types and their runtime checking with highly optimized code. This is why you see articles about the V8 Javascript engine's "inner classes" that tell you to avoid dynamically changing the structure of your objects or the types stored in your arrays, because that sort of thing prevents V8 from optimizing it down to "just 1s and 0s" that don't know their own types.

Hopefully those examples are sufficient to clear up your confusion.

0

You may think that

Console.WriteLine(myInt);
Console.WriteLine(myChar);

get compiled in the same way. But most likely the get compiled to something like

Console.WriteInteger(myInt);
Console.WriteEndOfLine();
Console.WriteChar(myChar);
Console.WriteEndOfLine();

On the other hand, some languages are very flexible. For example, Swift has the data type Any which can literally hold any value. An Any object is quite large, because it contains not only the value, but a complete description of the value. If you write

var myInt:Any = 5
var myChar:Any = '5'

then you have two objects of type Any, one containing the description of the "Int" type and an integer value, one containing the description of the "Char" type and a char value.

0

It depends on the language. In C, types exist only at compile time. In Java and C#, types exists both at compile time and runtime. In dynamic languages (like Python, JavaScript etc.) they exist only at runtime.

Your code example would therefore work quite different depending on the language. In Java/C# the two calls to Console.WriteLine() actually calls two different methods. This is called method overloading - multiple methods can have the same name, as long as they have different types of parameters, so the compiler can select the correct method implementation at compile time depending on the types of the arguments. The two different methods just happen to produce the same output in this specific case.

A dynamic language on the other hand would not have method overloading, but might have a single method which behaved differently depending on the runtime type of the argument.

-3

It depends entirely on the runtime. Java does it one way, .NET does it another, Python does it a third way, C++ does it a limited way, and C doesn't do it at all.

Such runtime type info might come either as metadata (or a pointer to thereof) attached to an object, or instead be static type info disguised as dynamic type info (e.g. C++'s typeid operator). But, again, it depends on the runtime.

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