Differences between statically/dynamically typed languages in programming

Artificial Intelligence Machine Learning Digital Transformation Ontology Technology Clojure Natural Language Processing Intelligent information Python PHP Prolog LISP CSS R language C/C++ Java Javascript Navigation of this blog Programming Overview
Data types and statically and dynamically typed languages in programming

In mathematicslogic, and computer science, a type theory is the formal presentation of a specific type system, and in general type theory is the academic study of type systems. Some type theories serve as alternatives to set theory as a foundation of mathematics. Two influential type theories that were proposed as foundations are Alonzo Church‘s typed λ-calculus and Per Martin-Löf‘s intuitionistic type theory. Most computerized proof-writing systems use a type theory for their foundation. A common one is Thierry Coquand‘s Calculus of Inductive Constructions.

In “Artificial Anencephalon Speaks of Zen and Buddha Bodhisattva,” Wittgenstein, who has read Russell’s “Principia Mathematica,” further discusses the relationship between the type of words and their meaning in the context of Zen philosophy.

A further mathematical approach would be related to the theory of spheres as described in “Gendai Shiso, July 2020, Special Issue: The World of Sphere Theory — Reading Notes on the Frontiers of Modern Mathematics.

In the previous article, from the May 2020 issue of Software Design, we discussed data types in programming and static and dynamic typing as the basics of types in computers. In this issue, we discuss the differences between statically and dynamically typed languages.

What are statically/dynamically typed languages?

A statically typed language is one in which the type of an expression is determined at compile time. First, in statically typed languages, variables have types: if you declare a: in Java, a is of type int. And a+1 is the variable a of type int plus 1 of type int, so the result is of type int. If a+0.5, then the result is a double, because in Java, int is expanded to a double and then added. Thus, in statically typed languages, the type of each expression, including subexpressions, is determined at compile time. Of course, the types of method arguments and return values are also determined. Otherwise, the form of the expression would not be determined.

The following figure shows a tree structure of the expression a+1+0.5.

If variable a is of type int, the type in each subexpression is represented by a square.

In contrast, in dynamically typed languages, variables do not have types to begin with. Therefore, the type of a+1 is not determined. In dynamically typed languages, types are added to objects at runtime. For example, when the value of variable a is 1, the following image is shown.

The statically typed diagram is a compile-time image, while the dynamically typed diagram is a runtime image.

In dynamically typed languages, the types of variables and expressions are not determined until runtime, so that even if you write meaningless code such as “divide a string by a string,” for example, no error will occur until runtime.

Even in a dynamically typed language, it is possible to assign a reference to an object of a subclass to a variable of a superclass type if it is an object-oriented language as described in “Object-Oriented Languages (1)” and elsewhere. And when a method is actually called, the method is called according to the type of the object, not the type of the variable (called polymorphism as described in “Polymorphism in Clojure” etc.), which means that the object has type information on its side. In other words, using a top-level class type variable such as Java’s Object or Scala’s Any, you can point to objects of any type, so it can be said that the language is practically the same as a dynamically typed language. However, in an actual program, you still choose the appropriate type for the variable, and in a statically typed language, the type of the expression (even if it is an Object) is determined at compile time.

Advantages and disadvantages of each – Performance

As a conclusion, statically-typed languages are generally faster to execute. As already mentioned, in a dynamically typed language, even a meaningless computation such as “divide a string by a string” is not known to be meaningless until runtime. Therefore, error checking must be performed at runtime, which inevitably slows down the execution speed. For example, the machine language instructions for adding integers and floating-point integers are different, so a dynamically typed language must also make such judgments at runtime.

Also, referencing object fields and method calls are faster in a statically typed language. In a statically typed language, when you want to reference a field, the number of the field in memory is determined at compile (or load) time, so it can be accessed immediately. (although hashing is used to speed up the process). The same is true for method invocation. In statically typed languages, a method can be selected at once from a virtual method table, but in dynamically typed languages, the implementation is usually to search for the method at runtime.

Nevertheless, for some applications, the slow speed of the language itself may not be a problem. For example, Ruby is used to build web applications such as Ruby on Rail. In web applications, the bottleneck is usually DB access or networking, so even if the Ruby part is slow, it does not affect the actual performance.

One solution is to “write in C or C++ where speed is needed. In recent years, it has become popular to use Python for machine learning. NumPy, a library for numerical computation, and TensorFlow, a library for deep learning, are written in C or C++ and can be used by calling them from Python.

Advantages and disadvantages of each – Ease of description

Another point of view is that dynamically typed languages are more concise in terms of source code because types must be specified in the source code for statically typed languages but not for dynamically typed languages.

For example, when considering a function (method) that adds two numbers, Java would use

int add(int a, int b) {
 return a + b;
}

whereas in typeless Javascript it is as follows

function add(a,b) {
  return a + b;
}

It is true that in Javascript, you don’t have to write “int,” but it doesn’t make much difference at this level. On the other hand, in more complex cases, static typing languages can be troublesome.

The following example shows the Java code for storing the Person class described in “Data Types and Static and Dynamic Typing Languages in Programming” in HashMap so that it can be searched by string-type user IDs.

Map<String, Person> personMap
=new HashMap<String, Person>{}:

This uses a feature of Java called generics, but in a dynamically typed language, generics are not needed in the first place. This is because there is no compile-time type checking anyway.

Java has been able to perform type inference for local variables since Java 10, so it can be written as follows.

ver personMap
= new HashMap<string,Person>{};

By the way, when we say that dynamically typed languages can be written more concisely, in some cases it actually does not matter whether they are dynamically or statically typed. There are many factors that make it look more concise, such as short reserved lines, no semicolons at the end of lines, and the ability to write statements at the top level (no need to write class and method definitions just to output a single line).

Advantages and disadvantages of each – Readability

In general, programs are easier to read when they are shorter. Therefore, one point of view is that dynamically typed languages with concise descriptions are easier to read. This was widely said more than a decade ago when people were talking about “moving from Java to Ruby,” and it is true that PC screens are getting wider and wider, and the more concise the description, the more you can see at once. When you are writing a source, your mind is focused on the source, so brevity is often effective in such cases.

However, when reading the source code after a while, brevity means that there are fewer hints, and while writing the source code, you may be able to remember the name of a variable, even if it is only one letter, but when reading it back later, you may not be able to understand what it is. The same thing happens with dynamically typed languages.

For example, the following Javascript code is a method that clears the “campus” passed as an argument.

clear(canvas) {
 let context = canvas.getContext("2d");
 … omitting the following

In the above code, it is hard to tell what this argument canvas is. In this example, if one has knowledge of Javascript, one can assume that it is an HTML5 canvas, but if it is a proprietary class of this program, how can one find its definition? If this is the original class of the program, how can we look for its definition?

It is often said that programs should be written with the reader in mind rather than the writer. This is because the time spent reading programs written by others is overwhelmingly longer than the time spent writing them. In this respect, the low readability of dynamically typed languages can have a serious negative impact on productivity.

Advantages and disadvantages of each – The mold is a guideline for design

In programming languages, it is widely said that data structures are much more important than the code that is executed. In this regard, statically typed languages have the advantage of being easier to understand because all data structures are defined in advance.

Programmers who mainly use statically typed languages start writing programs by first deciding on the data structures and interfaces (method signatures). Once that is decided, all that is left to do is to write the code accordingly, which is also helpful when writing programs in a team.

Advantages and disadvantages of each – Strength to change

Dynamically typed languages are said to be “flexible. In statically typed languages, data structures and method signatures are determined top-down and then code is written, whereas in dynamically typed languages, code is written and modified in an agile manner. Therefore, code written in a dynamically typed language can work to some extent even when the overall consistency is broken, which has the advantage of allowing the developer to check the code while making errors, especially in the case of web development.

On the other hand, in a statically typed language, if there are inconsistencies, the compiler will not allow the code to work unless all the inconsistencies are fixed. Conversely, the advantage is that if you fix all the points pointed out by the compiler, you can generally rest assured that it will work.

This means that a dynamically typed language is acceptable if all code can be passed through automated unit tests, but a statically typed language also has the advantage that corrections can be made on the basis of evidence in cases where test code cannot be sufficiently written because of rapid changes.

Advantages and disadvantages of each – Handling JSON files

Suppose you write some program and the configuration file for that program is written in JSON. For example, consider the following.

{
 "defaultWidth":800,
 "defaultHeight":600,
 "defaultSavePath":"C:\temp",
 "users":{"taro","jiro"}
}

If you are a programmer using a statically typed language, the first thing you would think of is to read JSON using some JSON parser and then assign it to a field in your own class, or use a function that maps JSON to a class. However, if this configuration value will be used only once, it will be troublesome to create a class for each use.

In such a case, if you use a dynamically typed language, the JSON parser can convert the configuration values into a hash or something, and you can retrieve the configuration values as in the following Ruby program.

defaultWidth = conf["defaultWidth"]

If this is a statically typed language, for example, even if the JSON parser converts it to a HashMap, when retrieving the value, a downcast is necessary because the type is not known.

int defaultWidth =
  (int)conf.get("defaultWidth");

In this example, if a non-integer value is listed in the defaultWidth of the JSON, an error will occur at runtime (ClassCastException). The runtime error is the same as in a dynamically typed language, so the advantage of static typing disappears.

It is natural that statically-typed languages are not suited to handle JSON, an expression format with no fixed type, but the advantage of dynamically-typed languages is that they can “plug in data whose type is not known.

About Type Inference – Java Type Inference

As mentioned above, since Java 10, instead of writing

Map<String, Person> personMap
 = new HashMap<String,Person>{};

It could be written as follows

ver personMap
 = new HashMap<String, Person>{};

This is because the compiler infers the type for you, and this is called type inference.

This example is called “local variable type inference” which is the simplest type inference, simply applying the type on the right-hand side of the assignment to the type on the left-hand side.

About Type Inference – Type Inference in Scala

For example, in Scala, the return type can be inferred as follows.

//Function to return arguments with arguments added

def add(a:Int,b:Int) = a + b

This is equivalent to writing The compiler will guess the return type Int.

def add(a:Int, b:Int): Int=a + b
About type inference – Haskel’s type inference

In Haskel, argument types can also be omitted as follows.

add a b = a + b

Besides, in Haskell, this add function can be used whether the argument type is an integer or a floating-point number.

print (add 3 5). --Displayed as 8
print (add 3.2 5) --Displayed as 8.2

In this way, although it looks like dynamic typing, Haskell is only a statically-typed language, and for example, if you pass a number and a string as arguments to the add function, you will get an error at compile time, not at run time.

The advantage of “concise writing” of dynamically typed languages can be achieved with statically typed languages if a language with type inference is used, but if the advantage of statically typed languages is “high readability thanks to explicitly indicated types,” then relying on type inference and not drawing types is a disadvantage.

Thus, both statically and dynamically typed languages have their advantages and disadvantages, and recently, dynamically typed languages such as Python and Clojure have begun to partially support types.

In the next article, I will discuss type hinting in Python, a dynamically typed language, and describe a type checker called mypy.

コメント

タイトルとURLをコピーしました