warp and weft
rehearsal
int n; or something like that.On p. 129, "Dynamic Typing > Advantages and Disadvantages," I wrote
Handling value types in this way allows for flexibility that was not possible with traditional statically typed languages. It is now possible to not determine the type until runtime, or to change the type at runtime. However, this was also a disadvantage. With statically typed languages, types were determined at compile time and type consistency was checked at compile time. Thanks to this type checking, some bugs could be caught before execution. With dynamically typed languages, however, this is no longer possible.
There was a growing need to resolve this disadvantage. This need was particularly strong in JavaScript.
There are two approaches to eliminate this disadvantage.
Approach A
B Approach
. The "statically typed" part of "writing a program in a statically typed language and converting it to JavaScript" varies from language to language; Dart was released in 2011 and was re-released in 2018 with a different type mechanism. Also, the term "statically typed" is often associated with "a typing mechanism like Java," but this is not necessarily true.
When I wrote this book in 2014, I could explain it in a simple composition of "dynamic typing v.s. static typing"; as of 2019, we are in a transitional period where concepts that once could be summed up in one word "static typing" are being broken down into finer pieces. There are examples, such as Python, in which a dynamically typed language acquires static type checking after the fact. And within "static typing," a new oppositional construct "nominal v.s. structural" has emerged.
.
When can type B be used in a context where type A is required?
For example, when can an object of type B be assigned to a variable x of type A? :
A x;
B y = new B();
x = y; // OK? NG?
double z = 1; was OK after Dart 2.1, but not before. These differences in behavior are not the main issue here)In nominal type system languages, types have names. Even if they have exactly the same structure, they are different types if they have different names. In the following code, T1 and T2 have exactly the same structure, but an error occurs when assigning them.
Dart
class T1 {
num x;
}
class T2 {
num x;
}
void main() {
T1 a;
T2 b = new T2();
a = b; // ERROR: A value of type 'T2' can't be assigned to a variable of type 'T1'.
}
In this type system, by explicitly declaring that type T2 is a subtype of type T1, it is possible to use T2 in contexts where T1 is required. In the code below, extends is the declaration of the subtype. Dart
class T1 {
num x;
}
class T2 extends T1{ // explicitly declared "T2 is a subtype of T1
num x;
}
void main() {
T1 a;
T2 b = new T2();
a = b; // now OK
}
On the other hand, in languages with a structural type system, types are judged by the structure they have. Types do not necessarily have names, and even if they have different names, they are treated as compatible if they have the same structure.
TypeScript
type T1 = {
x : number
}
type T2 = {
x : number
}
let a:T1;
let b:T2 = {x: 1};
a = b; // OK
The {x: 1} part of let b:T2 = {x: 1} in this code is an unnamed object type.
This has the same form as both T1 and T2, so it can be substituted without error.
C++, born in 1985, and Java, born in 1995, used a nominal type system. These two languages became so major that many people are familiar with declaring partial type relationships with extends and implements. On the other hand, structural type systems were more mainstream in type theory research. As a result, when designing statically typed languages to generate JavaScript, there was a mix of languages that adopted the nominal type system with reference to Java and other languages that adopted the structural type system with reference to type theory.
(The nominal type system had the advantage of a light process for determining whether a type was a subtype or not. However, 25 years have passed since the birth of Java, and the performance of computers has greatly advanced, so this may not be a reason for choosing the nominal type system. Rather, it is probably due to the historical background that there are many people who are familiar with Java).
(Java adopted the generic (generic type) feature in 2004. (Java adopted generic types in 2004. This is the direction in which Java, which used to be a nametype type, is now moving toward a hybrid with structural types, but whether or not to devote a page to explaining this is a matter for discussion).
Difference between a nomenclature-type system and a structural-type system.
This page is auto-translated from /nishio/「名前的型システムと構造的型システムの違い」加筆案 using DeepL. If you looks something interesting but the auto-translated English is not good enough to understand it, feel free to let me know at @nishio_en. I'm very happy to spread my thought to non-Japanese readers.