5

Functional/non-functional and interpreted/compiled are two different categorizations, yet it seems that there are a lot of overlaps in the programming languages that fall under those categories. Is this a coincidence?

8
  • 5
    So you are saying Haskell and ML family, eg. the most popular functional languages, are interpreted?
    – Euphoric
    Jun 15, 2014 at 6:14
  • 1
    They're not. The Lisp family used to be commonly considered interpreted (I still have old books that make the claim) but that's not true now and maybe never really was. However, unlike ML and Haskell, Lisp has dynamic typing. That means a tiny bit of work must be done at run-time (unless the optimizer can eliminate it) to determine which implementations of certain operations to use for particular values based on their types - similar to the tiny "overhead" for late-binding member functions in object-oriented programming. Dynamic typing is really just another form of late binding.
    – user8709
    Jun 15, 2014 at 7:13
  • Then again, Haskell is statically typed (and definitely compiled) yet has a similar tiny-but-there run-time cost for calling typeclass members - yet another form of late binding, really - and although I don't know much about ML, it probably has some equivalent too. In my mind, late binding is one of those things that shows that interpreting vs. compiling is blurry - though thinking of particular kinds of run-time work as left-over interpreting is probably a bit odd when the whole point of a program is to do work at run-time.
    – user8709
    Jun 15, 2014 at 7:23
  • 4
    You are confusing languages with interpreters/compilers. Many languages have both compilers and interpreters (REPLs) - a language is not defined by the execution environment/engine.
    – Oded
    Jun 15, 2014 at 7:57
  • 1
    @Oded: A REPL ist not the same thing as an interpreter. The Scala REPL is implemented with a compiler, as is Clojure's and GHC's. Jun 15, 2014 at 18:40

1 Answer 1

19

There is no such thing as an "interpreted language". A language is a set of abstract mathematical rules. A language isn't interpreted or compiled, it just is. Interpretation and compilation are traits of, well, the interpreter or compiler (duh!), not the language.

A language is an abstract entity, an interpreter or compiler is a concrete implementation of that abstraction. The two live on completely different levels of abstraction. The term "interpreted language" is not just wrong, it doesn't even make sense. If English were a typed language, "interpreted language" would be a type error!

You can't ask whether a language is an interpreted language, the answer isn't "yes" or "no", because the question itself is non-sensical. It's like asking whether orange is a prime number.

Every language can be implemented with an interpreter, and every language can be implemented with a compiler. You can automatically derive a compiler from an interpreter and an interpreter from a compiler.

The vast majority of languages have both compiled and interpreted implementations. The vast majority of modern high-performance language implementations are mixed-mode implementations which combine interpretation and compilation.

Now, let's look at some popular functional languages and some of their popular implementations:

  • Haskell
    • GHC, the Glorious Glasgow Haskell Compiler: obviously a compiler
    • UHC, the Utrecht Haskell Compiler: again, a compiler
    • JHC, also a compiler
    • HUGS (no longer maintained): an interpreter
  • Standard ML
    • SML/NJ (Standard ML of New Jersey): a compiler
    • MLton: a compiler
    • ML Kit: a compiler
    • Moscow ML: a compiler
    • TILT: a compiler
    • SML.NET: a compiler
    • Alice: an interpreter
  • OCaml: there is only one implementation of OCaml, a compiler
  • F♯: there is only one implementation of F♯ (Microsoft Visual F♯), a compiler
  • Scala: there is only one implementation of Scala, a compiler
  • Clojure
    • Clojure: a compiler for the Java platform
    • ClojureCLR: a compiler for the CLI platform
    • ClojureScript: a compiler for the ECMAScript platform
  • Scheme
    • Racket: compiles Scheme to bytecode, then either interprets or compiles that byte code
    • Stalin: a compiler
    • Gambit: a compiler
    • CHICKEN: a compiler
    • Ikarus: a compiler
    • Larceny: a compiler
    • IronScheme: a compiler
    • Bigloo: a compiler
    • Kawa: an interpreter
    • Gauche: an interpreter
12
  • "The vast majority of modern high-performance language implementations are mixed-mode implementations which combine interpretation and compilation." I would highly disagree. JIT is not interpretation.
    – Euphoric
    Jun 15, 2014 at 12:25
  • @Euphoric: where did I claim that it was? Jun 15, 2014 at 12:43
  • OCaml has something like two implementations in one: a normal compiler and a bytecode compiler. The first is a normal optimizing compiler while the second is more a mixed-mode system with a bytecode interpreter. They're shipped together, but are separate backends. Jun 18, 2014 at 16:29
  • @TikhonJelvis: I assume the latter one is used for staged compilation / compile time metaprogramming à la camlp4? BTW: "mixed-mode" refers to combining an interpreter and a compiler, but from what you describe, there is a pure byte code interpreter, no compiler, so "mixed-mode" doesn't really apply. Jun 18, 2014 at 16:35
  • @JörgWMittag: Well, you have to compile to the bytecode first. Perhaps I misunderstood what you meant by mixed-mode though. The bytecode compiler is used by camlp4, but that's a bit of a historical accident and makes it slow, so they're not using it for their new "extension point" system. Mostly, the bytecode compiler is useful for portability and simplicity: for example, it's used by js_of_ocaml to compile to JavaScript. I think it's also used for the REPL. Jun 18, 2014 at 16:42

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