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?

  • 5
    So you are saying Haskell and ML family, eg. the most popular functional languages, are interpreted? – Euphoric Jun 15 '14 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. – Steve314 Jun 15 '14 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. – Steve314 Jun 15 '14 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 '14 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. – Jörg W Mittag Jun 15 '14 at 18:40

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
  • "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 '14 at 12:25
  • @Euphoric: where did I claim that it was? – Jörg W Mittag Jun 15 '14 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. – Tikhon Jelvis Jun 18 '14 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. – Jörg W Mittag Jun 18 '14 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. – Tikhon Jelvis Jun 18 '14 at 16:42

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