Interpreters and Dynamically Typed Languages
Why are programs that have dynamically typed la开发者_如何学运维nguages usually interpreted rather than compiled?
In short: They go together like peas and carrots.
Compiling vs. interpreting and language typing are fundamentally separate concerns in that you can have all possible permutations. On the other hand, the "reason" for picking compiling and not picking dynamic typing for a language design are usually the same: performance. The "reason" for picking dynamic typing and interpretation are also somewhat related.
It's not a hard and fast rule. You can always mix 'em up. You can compile Perl and Lisp for example and interpret C.
You are observing a non-causal correlation:
- Dynamic typing and interpretation correlate because both are easy to implement.
- Static typing and compilation correlate because both are conducive of predictably-good performance.
Compilers are usually retrofitted onto dynamically-typed languages in an attempt to improve performance (because performance is often very poor). For example, here's how long some major dynamically-typed languages were interpreted for before their first compiler was written: Lisp (1958-1962), Mathematica (1988-2004), Lua (1993-2004), Python (1991-2002) and Javascript (1995-2009). In contrast, languages like OCaml (1996) and F# (2001) were released first as compilers.
As noted by others, languages are neither compiled or interpreted. They're just rules that need translating and most have interpreted and compiled implementations. Even then, it's hard to talk about interpretation versus compilation when many "interpreters" are jitting all over the place and some "compilers" are happy to compile-on-demand if a source file changes.
Maybe it's better to categorize implementations as fully pre-compiled or compiled-on-demand. If we use these categories, the one thing that breaks full pre-compilation is an eval function. This probably has more of an effect on the implementation than dynamic types. If you have an eval function, you're required to support compile-on-demand.
Common Lisp code is mostly compiled. The Common Lisp programming language has been described in an ANSI standard with support for compilation. The ANSI standard describes functions that compile code, describes various aspects of optimizations, describes aspects of the compilation process and more.
Interpreters for Common Lisp exist, but are less often used.
Common Lisp implementations often can mix different execution modes freely. Almost all have a compiler. A few only have a compiler.
Compilation in almost all implementations has an incremental mode, so that it can be used interactively. All can compile files. Some have 'block compilation' modes to compile groups of files.
Per the definition of dynamically typed languages...
A programming language is said to be dynamically typed when the majority of its type checking is performed at run-time as opposed to at compile-time. In dynamic typing, values have types but variables do not; that is, a variable can refer to a value of any type.
That said, it becomes hard to know what to compile the program down to since it could change at runtime. Another excerpt here from Wikipedia...
Dynamic typing allows constructs that some static type checking would reject as illegal. For example, eval functions, which execute arbitrary data as code, become possible. Furthermore, dynamic typing better accommodates transitional code and prototyping, such as allowing a placeholder data structure (mock object) to be transparently used in place of a full-fledged data structure (usually for the purposes of experimentation and testing).
I feel this answer is still incomplete but I hope it points you in the right direction. Perhaps others here can expand on this.
Checking types once is actually what makes a "compiler" (~ a type checker).
You can't "compile" (check types once) when types are "dynamic".
精彩评论