
The History of Compiling
Before we compare the two types of programming languages, we have to first talk about assembly languages.
Assembly language is a low-level programming language that has a one-to-one correspondence with Machine code(raw set of instructions, made of 0s and 1s… stuff that computers can directly understand and execute).
They came way before the popular high-level programming languages we have now, like Python or Java.
There was one crucial problem with assembly languages though: the machine code a computer uses depends on its specific architecture, and therefore, the assembly language corresponding to that machine code also differs for each architecture.
This meant that whenever a new CPU with a different architecture came out, programs that worked perfectly on the old CPU had to be completely rewritten in the assembly language specific to the new CPU. Really inefficient.
This inconvenience led to a strong demand for a unified language system that could be used to write code regardless of the underlying computer architecture. This is where high-level programming languages like Java, python, and C++ emerged.
One thing to keep in mind though is that as time went on, computers still could only understand machine code. So, the high-level code we write needs a translation process to become something, like an Assembly language, that the computer can execute. This translation is what we commonly know as compiling.
Compiler vs Interpreter
First, a compiler works by scanning your entire program and translating all of it into machine code before execution.
(EXAMPLES: Java, C, C++)
Pros:
- Since it translates the entire program at once, the overall execution time is typically faster than with an interpreter. (This is also why in programming competitions, like USACO, interpreter languages are generally more encouraged– due to time constraints.)
- Compilers provide error messages for the entire code after scanning, meaning that you can identify and fix errors even before the program even starts running.
Cons:
- The initial scanning and translation process takes longer(because duh, it reads everything at once)
- Compiling often requires more memory. After translating your source code into machine code, compilers create an Object Code file(compiled instructions in a machine-readable format). These object code files then need to be combined into a single executable file through a process called Linking.
In contrast to a compiler, an interpreter translates and executes your program one line at a time as the program is running.
(EXAMPLES: Python, Ruby, JavaScript)
Pros:
- Interpreters are typically more memory efficient. In contrast to compiler languages, they don’t generate object code files or go through a separate linking process.
Cons:
- Since interpreters translate and execute code line by line, the overall execution time is typically slower than with a compiler.
Based on perspective:
- Error detection works differently. In contrast to compilers, you can only identify errors after executing the code: interpreters compile line by line, so if it encounters an error while translating a statement, it will immediately stop the program.
Some might say that this makes debugging easier due to immediate feedback, and some others might say that this is annoying since there isn’t a way to look at the bigger picture. This is why I say this is mainly based on perspective.
Quick summary
To recap:
Compiler
- Scans the entire file and translates it all at once.
- Initial scan time is longer, but once an executable file is created, subsequent executions are faster.
- Uses more memory during the translation process (due to object code and linking).
- Provides all error messages before execution, allowing you to fix issues early.
- Examples: Java, C, C++
Interpreter
- Translates and executes one statement at a time during program execution.
- Execution time is generally slower because of the line-by-line translation.
- More memory efficient as it doesn’t create object code files.
- Discovers errors during execution, stopping the program immediately when an error is encountered.
- Examples: Python, Ruby, JavaScript.
Leave a Reply to Ian Cancel reply