What exactly is the difference between interpreting and compiling languages?
As a beginner software engineer, I enjoyed working with Swift in Apple’s Xcode. Errors and warning messages would appear immediately after mistakes were made, the console printed all my function returns as they were typed and program execution was “swift”.
When I began working with Ruby in Atom’s text editor, I was terrified that suddenly all my red flags and caution signs were gone and I could literally type anything with no sense of the danger that lay ahead. More often (and more sinister), I could add an extra ‘p’ in my “happiness” method and spend over an hour debugging to find it. Then of course the console had to be told when run my program, and it was slower to load than with Swift.
Then I grew to love the benefits of Ruby: I could quickly write my code without all the random crashes of my Swift applications while I was typing, even when I had made no errors.
Other than language syntax, why did I have two very different experiences? The answer I would learn mainly had to do with how these two high-level languages were translated into machine code on my user’s device.
Compiling and Interpreting Languages
There are two main types of high-level languages: ones that are compiled and ones that are interpreted. As I don’t have a computer science degree, this description however did not make sense to me. I would learn that it’s best not to chain a coding language to the adjectives “compiled” or “interpreted”, but to think through processes of compiling or interpreting source code.
“The difference is not in the language; it is in the implementation.”Norman Ramsey
At runtime, languages that are commonly compiled, such as C, C++, C#, Scala or Swift, are processed as an entire program. This means that all models, views and controllers are assembled at the same time, and in the case of applications like Xcode, the code was already checked and partially assembled beforehand. This means the program has generated all its objects and is then able to be quickly deployed.
With languages that are commonly interpreted, such as Java, PHP, Python and Ruby, there is no preparation and instead runtime processes code one…line…at…a…time. This results in slower execution but provides the benefit of using less memory. The one-line-at-a-time method also comes in handy in that errors can be easily located and printed in the console with its error-type.
Which should you pick?
This will mostly be decided by which languages, tools and areas of software or web development you happen to begin with.
I found the experience of working with compiled languages fantastic in that there is a bit more flexibility in the ordering of definitions, instances, required files and extensions. When working with a language that is being interpreted every single line of code must follow a precise order as that is how it will be interpretted.
“The benefit of a compiled language is that you can take the machine code and theoretically run it anywhere.”Andrew Cohn
The difference can feel a bit like hanging out with that friend who just gets you and you can take anywhere (a compiler) and that friend who really takes everything way too literally and you’d only ever meet them in your mother’s basement (an interpreter).
At runtime that “compiler” friend can often be ambiguous and conflicts are difficult to pinpoint, while with that “interpreter” friend you always know exactly where you stand with them and immediately let you know if you’ve done something wrong.
The more languages I learn and environments I use them in, the more I’m beginning to understand all the near-miraculous ways that computers can function and the incredible work of those who’ve come before me. The interpreting and the compiling of languages is just the beginning of peaking underneath the power of high-level languages.