CSC/ECE 517 Fall 2009/wiki1b 2 ps
Advantages of statically typed vs. dynamically typed languages
Type checking can be performed in programming languages either during run-time or at compile time[1]. Based on such a behavior of the type system, the programming languages are classified as statically typed or dynamically typed. The statically typed languages like C, C++, C#, Java, FORTRAN etc., eliminate the type checks to be performed every time the program is executed [1]. The condition checked once will hold good for all the future executions of the program as well. The dynamically typed languages like PHP, Prolog, Python, Ruby, Smalltalk etc., perform the run-time checks uses the information from the compile time as well and hence could be more comprehensive[1].
Typed and Untyped languages
The languages can defined based on how the data types are associated with the variables in the programs. Based on this, the programming languages are categorized into typed and untyped languages. The “type” provides the information about the chunk of memory which holds the data and thus categorizes it such that the valid operations that can be performed on that data are defined. In object-oriented programming, the types include classes (user-defined), strings and integers (primitive types), lists/arrays/vectors/hash (containers) [2]. A variable in a program can accept a certain range of values during its execution. The upper bound value for that range marks the type for that particular variable. For example, if there is a variable num of type int in the program then num can accept only integer values during every execution of the program. Such languages where all the variables are associated with the data type are called typed languages. Certain languages do not specify separate data types for each of the variables but contains a single universal type that holds all the values. They do not define the range for the variables and are called untyped languages (assembly languages) [4]. Depending on when (compile time or run-time) the the “type” of the variable is checked, the typed languages can be classified as statically typed or dynamically typed.
Type Checking
Type checking is done only for the typed languages. All the variables and expressions in the program are associated with the data type. Errors might occur due the explicit or implicit mismatch of the type information. Type checking identifies the errors that may or may not produce wrong computations in the program [3]. In order to eliminate these errors the programming languages have the type systems. Type system is programming language specific and defines the rules of how the typed programs should behave. The programs which do not follow these rules produce error [1]. The type system performs the static check on the statically typed languages and dynamic check on the dynamically typed languages.
Statically typed languages
In statically typed languages, types are associated with the variables or the expressions and not the values. The type checking is performed at the compile time and thus many types of errors can be identified in the early phases of the development cycle [1]. Consider the code of the program below. It shows the illegal statements in the code the static-type checker will identify.
int num; num = “Assign a string”; //Type error ArrayList aList = new ArrayList(); //Collection from Java int array[] = aList; //Type Error
Advantages and Disadvantages
If the static type checks are performed once for a program, there is no necessity to perform the check at every execution of the program. Thus the execution can be efficient by eliminating the run-time checks. Certain programs may exhibit a desired behavior at run-time but since the static type checkers do not have the type information that might be available only during run-time, they might consider identify errors is such programs even though they might be resolved at run-time[1]. For example, consider the code in a program –
int x; if (expression is true) then <perform computation> else x = “Error” // int cannot take the string “Error” – type error
Though the expression might always return true at run-time, the type error will be thrown by the static type checker as expression will not be evaluated at the compile time and there is no way for the type checker to know that the execution will not perform the else part of the code. However, if the expression randomly evaluates to false, the static type checking could be of great advantage [1].
Dynamically typed languages
In dynamically typed languages, the types are associated with the values. The run-time checker identifies the type errors at the run time [1]. Consider the code of the program below, since the type information is not known at the compile time, the addition of the character and an integer will result in run-time error.
a = [‘x’, 1, 2] b = a[0] + a[1] #Type Error
Advantages and Disadvantages
The dynamic type-checker offers more flexibility to the programming language as types and functionality can be generated on the data obtained during run-time [1]. Also it accepts the code often invalidated by the static-type checker and executes it. Though the checker checks for the syntactic correctness of the code, it might not perform all the checks that are performed by the static-type checker. Nevertheless, it incorporates both the static-checking and dynamic-checking functionality. The checks are exclusively for the conditions which are part of the execution of the program and it holds good for all the executions of the same program [1]. The dynamic type-checking might be slower as more emphasis is on the optimization of the libraries and improvisations of the algorithms hence the efficient coding tricks might not be completely taken care of [5]. While evaluating an expression, sometimes the value might have been passed to the wrong type and computation might produce erroneous results. If this error occurs long after the mistake was made in the code, bug location might be difficult [1].
Comparison of statically typed and dynamically typed languages
One of the key features of the dynamically typed language that the statically typed language lacks is duck typing. In duck typing, when the methods are invoked the aspects of the object invoking that method is important and not the type of the object. In languages that do not allow duck typing, if there are functions f1 and f2 defined in Class A, then the object of type Class A can invoke the functions f1 and f2. However, in languages that do allow duck-typing, an object of any type (not necessarily of type Class A) can call the functions f1 and f2. Consider the code below of an dynamically typed object-oriented language, the function add can be invoked by the objects which do not have any related inheritance (numbers and strings). Thus, duck-typing allows polymorphism without inheritance [9].
class A{ int add(x, y){ return (x+y); } } num = add (10, 20); str = add('A', 'B'); puts num; puts str; Output: 30 AB
Statically typed languages are considered to be strongly typed as it prevents the program from running if it has errors in the code and dynamically typed languages are weakly typed as programs are allowed to run even if they have errors in them and they are detected during run-time.
Though the static-checking is done for the statically typed languages, many languages postpone the type checks to the run-time. The static checker mainly builds on the correctness of the code that the developer writes. If the type information is not provided by the developer to the type system, the static checker cannot detect some of the common errors in the code. For example, if the variable is declared to be of the type int by the programmer and as per the program logic, if it should be of type float the type checker will not detect it. In statically typed languages, since the type declaration has to be done explicitly, if the data type is changed for a variable at a single place in the code, then the corresponding changes have to be made everywhere in the code with respect to the logic and usage. Consider the Java code below - say a variable test is declared of type String and the in-built method of String class, toLowerCase() is used to convert test to lowercase. If test is changed to type int, the developer has to manually change/delete test.toLowercase() in the code.
#Java code String test = "ABC"; #code test.toLowerCase();
If the above scenario spans across multiple files, it becomes tedious and makes the code error-prone. Hence static type systems are not flexible and difficult to work with[6].
Some of the statically typed languages require lot of type declarations and in most cases, more declarations than necessary. This makes coding more time-consuming and also very difficult to make changes[7]. This could pose a problem while writing reusable software and also reduces the agility of the programming language. Thus, dynamically typed languages are best suited for the rapid application development. However, static-checking makes the software more reliable as they find errors at compile time[6].
Static type systems help in producing readable software and this corresponds to the self-documentation of the source code. Since the type information is present in the code, it is easier for the developer to walk through the code when compared to the dynamically typed languages where the code might get confusing [7]. Since the variables are not associated with the data type in dynamically typed languages, while reading the code it would be difficult for the developer to know the association between the variables and the data types. The static type system helps in providing the developers with intelligent development tools that have various features like auto-completion (intellisense) and other analysis tools that makes programming easier [8].
Though the statically typed languages are much faster than the dynamically typed languages as in the latter type checking is done at run-time, currently the memory and performance are not the major issues for most of the applications (with the exception of embedded systems on large application servers) and dynamically typed languages cannot have disadvantages due to performance concerns. Instead, dynamic type systems give the developers the boost with the reduced development time [6].
With respect to the testing, static type systems perform better than dynamic type systems. The static systems can many a times tell if the changes to the code has broken any other piece of code. Thus in certain cases testing might not even be required [7]. It is fairly effective to find type errors in code through static type checking than the code coverage tests with 100% code coverage [1].
If the compiler can determine the exact types that are used in the code, it can generate the machine code with optimizations. Hence the compiled code of the statically typed languages executes more quickly. For this reason, certain dynamically typed languages like Common Lisp provide the optional type declarations facility for the optimizations [1]. In dynamically typed languages the type checking is not performed until run-time and hence it has very less code to visit and this reduces the time and effort involved in editing, compiling, testing and debugging the code [1].
Static typing provides effective re-factoring of the code. For instance, the programming environment of the statically typed languages can analyze the source code and all the callers of a particular method. Using the tool, the method could be renamed throughout the source code at all of its occurrences. This is difficult to accomplish in the dynamically typed languages as the reference of name is determined only during run-time [1].
Based on the above discussions, features of type systems can be categorized as follows [1]:
Features | Statically typed language | Dynamically typed languages |
---|---|---|
Safety | Type errors are found at compile time thus more reliable. | Type errors are found at run time, less reliable. |
Optimization | Provides compile code.Execution is faster as complied machine code is readily available. | Optimization is option in some languages but its done at run time. Its faster. |
Documentation | More expressive, easy to understand for the developers. | Not structured, confuses the developer. |
Performance | Time consuming and less flexibility. | Reduced development time.Suitable for rapid application development. |
Statically and dynamically typed languages have their own advantages and disadvantages and which one to choose depends on the application one needs to develop and various other factors. Java vs. Python comparison gives us the idea of how the above languages differ in terms of type information, verbosity etc.
References
[1] http://en.wikipedia.org/wiki/Type_system
[2] http://www.artima.com/weblogs/viewpost.jsp?thread=7590
[3] http://www.cs.aau.dk/~normark/prog3-03/html/notes/fu-intr-1-show-types-and-check-1.html
[4] http://www.eecs.umich.edu/~bchandra/courses/papers/Cardelli_Types.pdf
[5] http://tratt.net/laurie/research/publications/papers/tratt__dynamically_typed_languages.pdf
[6] Laurence Tratt, Roel Wuyts, "Guest Editors' Introduction: Dynamically Typed Languages", IEEE Software, vol. 24, no. 5, pp. 28-30, Sep./Oct. 2007
[7] http://www.pphsg.org/cdsmith/types.html
[8] http://www.martinfowler.com/bliki/DynamicTyping.html
[9] http://en.wikipedia.org/wiki/Duck_typing
External Links
[1] http://en.wikipedia.org/wiki/Ruby_(programming_language)
[2] http://lambda-the-ultimate.org/node/100
[3] http://en.wikipedia.org/wiki/Programming_language#Typed_versus_untyped_languages
[4] http://livedocs.adobe.com/flex/3/html/help.html?content=03_Language_and_Syntax_09.html