0

While reading the difference between Compiler and interpreter , I found the following differences fromt he internet.

Advantages of using compiler:

  • Since compiler converts the program to native code of the target machine (object code), faster performance can be expected.
  • There is a scope for code optimisation.

Advantages of using interpreter:

  • Process of execution can be done in a single stage. There is no need of a compilation stage.
  • Alteration of codes possible during runtime.
  • Really useful for debugging the codes (because source code execution can be analyzed in an IDE)
  • Facilitates interactive code development.

In case of interpreter, stated as interpreter "there is a possibility of alter the code" and

In case of compiler "code optimization will be there"

Can anyone explain these 2 points ?

2
  • 6
    Do not read the internets, they're lying. All the points above are just pure nonsense.
    – SK-logic
    Commented Dec 13, 2013 at 15:35
  • f2c (fortran to c) and p2c (pascal2c)... or CoffeeScript are all compilers in that they compile from one language to another - just not necessarily compiling to the 'target' machine. And lots of languages compile to C. On the flip side, in Java (a 'compiled' language), most optimization is done at runtime, not compile time.
    – user40980
    Commented Dec 14, 2013 at 1:05

6 Answers 6

5

Side note: use compiler/interpreter distinction carefully, as it has its caveats.

  • Some folks use this distinction to assert that their language is faster because it is compiled/interpreted. The real answer is that a language cannot be faster/slower than another one: is German faster than Japanese?

  • Many other assertions related to this distinction don't make sense neither.

  • Many languages use more complicated approaches. For example, C# is compiled to IL, which is then “translated into native code or executed by a virtual machine”.

  • Some languages are “interpreted, but not really”.

Now to answer your question:

Altering the code:

Since the code is interpreted, it's easier to change it on the fly when executing it. One of such examples is eval(), used in some languages to dynamically inject source code available only as a string.

This being said, this point is both incomplete and confusing. C# is a compiled language (aside DLR), and still, there are ways to inject custom code during the execution of the app.

Code optimization:

Often, compilers are not limited to simply converting code written in source language to target language. They also do optimizations. Imagine you write:

const int ratio = 14;

function getFactor()
{
    int factor = 2 * ratio;
    string debug = "The factor is " + factor;
    return factor;
}

function computeSomething(int expenses)
{
    int factor;
    float result = (float)(expenses + factor) / 2;
    return result;
}

A compiler can use a few basic tricks to optimize this code:

  1. Inline

    The constant can be inlined, as well as the first function. This gives:

    function computeSomething(int expenses)
    {
        int factor = 2 * 14;
        string debug = "The factor is " + factor;
        float result = (float)(expenses + factor) / 2;
        return result;
    }
    
  2. Remove unused code

    Here, this will result in an important improvement, since string concatenation is often an expensive operation.

    function computeSomething(int expenses)
    {
        int factor = 2 * 14;
        float result = (float)(expenses + factor) / 2;
        return result;
    }
    
  3. Optimize mathematical operations

    Float multiplication is often cheaper than division.

    function computeSomething(int expenses)
    {
        int factor = 2 * 14;
        float result = (float)(expenses + factor) * 0.5;
        return result;
    }
    
  4. Remove intermediary variables

    function computeSomething(int expenses)
    {
        return (float)(expenses + (2 * 14)) * 0.5;
    }
    

Note that many today's interpreters also do those optimizations, which means that when you use an interpreted language, you should write your code for humans, not for computers, letting the interpreter do work.

6
  • "This being said, this point is both incomplete and confusing." I would not say that. C# does allow you to inject new code. But it doesn't allow you to change structure of data or code that is already loaded. There is slight difference between adding new and changing existing. And the difference between compiled and interpreted is in the change of existing.
    – Euphoric
    Commented Dec 13, 2013 at 7:40
  • @Euphoric: interesting remark. I'm pretty sure there is a way of screwing things up by modifying existing code; I'll search for an example. Commented Dec 13, 2013 at 7:47
  • I don't know about Japanese, but I can say that e.g. English is "faster" than German (you can say more in less time and you can write more in fewer words). :-)
    – sloth
    Commented Dec 13, 2013 at 7:48
  • @DominicKexel: a slightly more exact analogy is if orders you give in English would be executed faster than orders you give in German. Commented Dec 13, 2013 at 8:36
  • 5
    "Some folks use this distinction to assert that their language is faster because it is compiled/interpreted. The real answer is that a language cannot be faster/slower than another one: is German faster than Japanese?" Actually I'd say that languages aren't compiled or interpreted, implementations are. It's perfectly reasonable to compare implementations Commented Dec 14, 2013 at 3:52
0

After thinking about it a little I'm changing my answer a bit.

Every language can be compiled. But the problem is how much do you gain from such compilation. Compilation has two benefits: performance gain through optimalizations and early error checking through checking of type signatures. Both of those things depend heavily on indirection in code. Indirection is simply piece of code, that you can tell what will happen only when the code is running. In both cases of optimalization and type checking, any kind of indirection renders any attempts useless. Compiler cannot optimize code if it doesn't know what is going to happen next or what structure will function return and it cannot ensure if types are correct if it doesn't know what parameters the function can accept or what is contained in a variable.

Now, the languages that are usually compiled, like C++, C# and maybe Java, those contain little indirections. In C# for example indirections can only be achieved through virtual methods and delegates. Everything else is simple to predict without having to run the code. If you call Math.Sqrt, then compiler knows 100% it is going to call this one method only. The gain from compiling those languages is huge.

On the other side, languages that are often interpreted usually have tons of indirections. This often stems from dynamic type system. In python for example, reading attribute from class can return absolutely anything at any time. You never know if read attribute will be int, string or function pointer. So even if you compile those, the gain is pretty negligible. The compiler can maybe pre-parse the code and do some minor optimalizations, but it cannot do things like function inlining, which usually have much bigger impact on performance.

Edit, old post:

I don't know what exactly you don't understand, because both those points are pretty self-explanatory.

With compiled languages the structure of code and data is static during compilation and cannot change during runtime. This does not stem from using compiler, but is requirement to be able to compile a language. The static structure then give compiler information necessary to predict how code will execute and optimize it out. Languages like C++, C# or Java fall into this category.

With interpreted langauges, the structure of code and data can change. Usually, when the structure is not static, compilation becomes close to impossible, so interpretation is required. But, because interpreter doesn't require the static structure, language can contain feature and semantics that allows you to change the data and code at runtime. Dynamically typed languages like Python, Ruby or JavaScript fall into this category.

5
  • All the points are totally meaningless, no no surprise a sane person cannot understand them. "With compiled languages the structure of code and data is static during compilation and cannot change during runtime." - wrong.
    – SK-logic
    Commented Dec 13, 2013 at 15:39
  • @SK-logic Then tell me how is it possible for compiler to optimize and ensure type safety if it doesn't have information about structure of data during compile time. Maybe they will give you Nobel Prize for that.
    – Euphoric
    Commented Dec 13, 2013 at 22:18
  • The wrong bit is the word "static" - code can be transformed dynamically during compilation (the simplest example is lisp macros in compile time). And of course a compiled code can change in runtime, if compiler is available (as in .NET, JVM, lisps, etc.). Also, compiler can defer some parts of code generation until late, as in .NET generics. There are hundreds of ways.
    – SK-logic
    Commented Dec 13, 2013 at 23:01
  • @SK-logic In first case, you are transforming data, not code. In LISP, code and data is same thing. In case of .NET and JVM, you can add code, but you can't change already loaded code or structures. And generics are still quite static, because there is only limited scale of them.
    – Euphoric
    Commented Dec 13, 2013 at 23:08
  • It's a terminological (i.e., useless) argument. In lisp code is dynamically transformed in the compilation time (and any code is data anyway). In many lisps (e.g., in Common Lisp) code can also be replaced in the runtime. Generics is an example of how not knowing implementation details does not stop a compiler from producing code.
    – SK-logic
    Commented Dec 14, 2013 at 12:22
0

tl;dr: Once upon a time, there were compilers, and there were interpreters, and each could be clearly identified. Now, most compilers and most interpreters are somewhere in between.

  • Not all compilers compile to native code - e.g. Java
  • Many interpreters are actually compilers behind the scenes (Perl, Python etc.) and so can do the same optimisations
  • Alteration of code is done, in my experience, more in compiled code than in interpreted code; both at compilation time (e.g. C's #ifdef) and very occasionally in binary code (very specific optimisations, or to hide what the code is doing). Compilation time stuff is very, very common, binary code is very, very rare.
  • Compiled code usually contains a symbol table, so you can find out what line in the source code a piece of compiled code corresponds to. Facilitates interactive code development.

Altering code at runtime (which can, actually, be done both by an interpreter or compiled code) is a very dubious strategy, and error prone. I have seen it done in compiled (assembly) code more than interpreted code, and it tends to be a very small piece of code, which is VERY time critical, or for DRM purposes (where the author of the code does not want you to be able to figure out what he's doing). I've also seen it done for very, very wrong reasons.

As for "interpreted" code, most modern "interpreted" languages do "just-in-time" compiling - that is, when you run the code, the "interpreter" compiles the code (often into bytecode), and so can (and do) do code optimization too. In some cases, the compiled code is even cached, to be reused if the source file is not changed. An example of this is Python, which stores compiled bytecode in .pyc files.

Not all compilers compile to native machine code; java, for example, is compiled to java bytecode, to be run by the java virtual machine, which, in a way, is an interpreter. To confuse things further, some java virtual machines are themselves "just-in-time" compilers. Some even compile bytecode used frequently, and interpret the rest.

0

The best sample for your question will be SmallTalk system/language.

Classical ST system uses a virtual machine, executes bytecode. When you start system it loads from snapshot image, containing all bytecode compiler, IDE, debugger, visualization tools, editor, web browser, custom applications written as extensions to base ST, and all development environment is written in ST and compiled into bytecode.

So, in a debugger you can open any point of the whole system (or your application), edit its source code, and recompile this code on the fly, replacing code in runtime in running application. So system let you see elements in compiled form, in source code, and transform them manually or programmatically.

For example, in interpreter you can get source code for any function as AST, do some transformations (replace generic operations by its more optimized variant for current platform, for example replace all [+ L:... R:...] by [add_uint16 L:... R:...] ), and recompile resulting function in runtime. Or construct some computation code by program, and run it as bare machine code using optimizing JIT compiler embedded into your interpreter runtime system.

In case of a compiler (no matter bytecode or machine code), you lost a lot of meta information about your program (data types, generic templates,..), and have no ability to modify it at runtime.

1
  • It is not necessary to lose information during compilation. The "losing data types" claim is easily dismissed by pointing out that RTTI is available even in compiled languages. And generic templates can also be retained after "compilation", I think Graal/Truffle does this to be able to deoptimise and reoptimise code.
    – Mael
    Commented Oct 31, 2017 at 14:38
-3

As a practical example fire up EXCEL and create a macro.

Start the debugger and step through the code.

You can change the contents of any variable. Execute arbitary expressions. Change the source code (to a limited extent -- you cannot change code inside a loop or other control structure if the current statement is inside the structure etc. etc.)

1
  • 1
    This doesn't count. In Visual Studio, you can change code while being in debug mode as well (see Edit and Continue feature), and still, C# is compiled, not interpreted. Commented Dec 13, 2013 at 9:12
-3

The statement is highly arbitrary because there are also code injection techniques which alter compiled programs. With interpreted languages it's just easier to do.

A lot of virusses work this way.

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