No matter what programming language you use, you write your code in a human-readable way. Operators usually resemble math symbols; keywords consist of short English-based words, and built-in functions also have roots in natural languages. The problem is that the computer cannot understand human speech and texts directly, and we need to translate the meaning of our programs into the instructions for the processor. That's why we need compilers and interpreters.
Machine code
First, we need to know what language a processor, the brain of a computer, can understand. We'll call this language the 'machine code'.
Machine code is the binary representation of a program consisting of ones and zeroes that the processor of your computer can read directly. We can write the machine code right in the text editor, but we can hardly 'read' this code. The purpose of programming languages is to make programs more readable for humans, and the purpose of compilers is to make the code more readable for computers.
So, what is a compiler then, and how can it help us?
Compilers
Although we've started the discussion with the explanation of the machine code, the term compiler has to do with a lot more than that. See for yourself!
A compiler is a program that can translate the code written in one programming language into another language, as simple as that! It's just a program that turns one programming language into another, meaning you can write a compiler that turns the machine code into your favorite programming language, too.
Though compilers can do a lot more than create machine code from programming languages, you should know that the term is mostly used for this type of software.
Usually, compilation aims at creating an executable file, i.e. file consisting of machine code, that you can launch from your terminal or desktop environment, but during this process of compilation, the structure of your code can also be changed and optimized. A compiler is not just a tool that maps one instruction into another, it's a sophisticated program that represents your code in the most suitable way for the processor. That's why we also use compilers: they make our programs faster, lighter, and cheaper to run.
Nonetheless, this approach has some flaws. For example, we cannot see the result of the execution right away after we type a line of code. That's why with some programming languages there is another way to run programs, to interpret the source code.
Interpreters
Let's start with an illustration that shows the difference between the work of an interpreter and a compiler. As you see, there is one step less in the "How Interpreter Works" part:
So, an interpreter is a program that reads the source code line by line and converts it to the machine code on the fly. However, the expression on the fly should not deceive you, the actual speed of a program running with an interpreter is slower than the pre-compiled machine code because the interpreter spends time converting the source code and cannot do some optimizations available to the compilers.
The main advantage of that interpreters is that with them we can run our program on any machine. The compilation to machine code, on the contrary, is usually platform-dependent, and we need to compile the program for each platform separately. So that's why, for example, Java has a compiler to prepare the object code and the interpreters to run the object code on any machine.
Another useful feature of interpreters is that they provide easy try-and-explore interfaces for programmers. You can launch the interactive interpreter for languages like Python or JavaScript, type the command and immediately see the result of the execution.
Conclusion
To wrap-up:
If you run a computer program, you need to prepare the machine code for it.
Creating this code by hand is almost impossible, so we have two different strategies for it: compiling and interpreting.
Compilers can create fast and optimized machine code, but after the compilation, we have platform-dependent executable files.
Interpreters are simpler to use for programmers and can run the same code on different platforms, but the speed of execution is slower compared to compiled programs.