We have been talking a lot about compilers, and in this episode we discuss the differences between compilation versus interpretation. An interpreter is also a translator, just like a compiler, in that it takes a high level language (our source text) and converts it into machine code. However, it does something slightly different: it actually runs and executes the code that it translates immediately (inline) as it translates.
This episode of the Basecs podcast is based on Vaidehi's blog post, A Deeper Inspection Into Compilation And Interpretation from her basecs blog series.
[00:00:02] SY: Welcome to the Base.cs Podcast where we explore the basics of computer science concepts. I’m your host Saron, Founder of CodeNewbie.
[00:00:08] VJ: And I’m Vaidehi Joshi, Author and Developer.
[00:00:11] SY: And she is the brilliant mind behind the Base.cs Blog Series. Today, we’re talking about…
[00:00:15] VJ: Interpretation and Compilation.
[00:00:19] SY: This season of the Base.cs Podcast is brought to you by DigitalOcean and Heroku. DigitalOcean’s cloud infrastructure is optimized to make it super intuitive and easy to build faster and scale easier. The pricing is predictable. They have flexible configurations and excellent customer support. Get started on DigitalOcean for free with the free $100 credit at DO.co/basecs. That’s DO.co/basecs.
[00:00:47] Did you know you can build, run, and operate applications entirely from the cloud? With Heroku’s intuitive platform, you can streamline development using the most popular open source languages, so you don’t have to worry about backend logistics. Also, you’re not walk-in to the service. So why not start building your apps today with Heroku?
[00:01:12] SY: We started this entire show all of Base.cs by looking at binary and we started the show by talking about binary, what it was, how it worked. We counted in binary, if you remember. It was so much fun.
[00:01:25] VJ: We were such sweet summer children.
[00:01:27] SY: Oh summer children!
[00:01:28] VJ: We’ve come so far.
[00:01:30] SY: We have come so far. But let’s go back for a second and let’s remind ourselves what binary is. So what is binary all about?
[00:01:38] VJ: So binary, the way that we often think about it is the zeros and ones that a computer reads. And we sort of talked about how computers have switches and on off circuits and they sort of map to the zeros and ones that it basically parses and makes sense of because that’s how computers eventually do anything is with zeros and ones. But really the binary code that a computer reads and understands, it’s like the machine language. It’s like the language of that computer, and we refer to it as something called “machine code”. So the actual term binary is like the number system. But when you’re really talking about the language that a computer understands, you’re talking about the machine language, the machine code, and that can be different based on different kinds of languages, and it’s sort of like a program that can get converted down into binary by the machine. It’s like machine readable. That’s the really important part. It’s really just a set of instructions that you give to the machine and then the central processing unit, the CPU reads it, and there’s like some magic in there about how it actually turns it into binary. But like that’s the thing I never said in episode one is that there’s machine code, but that is what it is.
[00:02:55] SY: Okay. So machine readable code is super important for the machine, but obviously we cannot, well, I guess technically we could, we probably don’t want to.
[00:03:04] VJ: No, I don’t think we want to.
[00:03:05] SY: No, I don’t think we want to. We don’t want to write machine code ourselves. We want to write human readable codes. So I guess the big question is, how do we go from our human readable code, our Ruby, our Python or whatever, to our machine readable code?
[00:03:21] VJ: With the help of a translator.
[00:03:26] SY: What’s a translator? Does it translate?
[00:03:29] VJ: You hit the nail right on the head, Saron. A translator does in need to translate. Well, a translator, it’s basically like a programming language processor, and what that means is it takes whatever human readable code that you’re writing, which we can refer to as the source language or source text, and it translates that source language into something called a target language, and that’s going to be the language that the machine understands, the machine readable code, and it does that translation while also maintaining the logical structure of the code it’s translating. So it’s like sort of doing like a one to one where it takes.
[00:04:11] SY: Yeah. It’s intact.
[00:04:12] VJ: Yeah. it’s not really changing the structure of the code. It’s just translating from human readable to machine readable.
[00:04:19] SY: Okay. So we’ve talked about compilers last episode, and I think the episode before that, if I’m remembering correctly. So it sounds like what a translator does is also what a compiler does. Is a compiler a type of translator or is there a relationship there?
[00:04:33] VJ: Yeah. A compiler is one of the types of translators that you can use when you’re trying to translate between a source language and a target language. And we’ll recall from the last few episodes that a compiler has two different phases. It has that lexical analysis phase and the syntax analysis phase.
[00:04:51] SY: Yes.
[00:04:52] VJ: Basically, that whole process, all of those phases that a compiler goes through, those are all steps in its translation process because all it does is take a high level language and convert it down into machine code, and we won’t get into like the itty-bitty parts of that just because like you could do a whole series on compilers probably. But the important thing about compilers when it comes to translation is that compilers do all of their translating in one fell swoop. So what that basically means is a compiler looks at that source text, that source language, and it translates all of it first before ever running that code or like executing the code that it compiles it into and it’s sort of like do it in one shot. I translate it all at once.
[00:05:44] SY: Okay. So you go through the compilation process with our compiler and you spit out, I guess you end up just with like a pile of machine code. Is that what you end up with?
[00:05:56] VJ: Yes. That pile of machine code is also known as an executable.
[00:06:02] SY: Ah, yes.
[00:06:03] VJ: If you ever like downloaded a file and it’s ended in like .exe somewhere from the internet, and then you’re like, “Oh, just download this and then type this command or whatever,” and it’s like something .exe, that’s just an executable and it’s just a file that can be executed. It executes the translated version of whatever the compiler translated, and you don’t actually need the compiler at that point. The compiler is already done and gone. It’s done its job.
[00:06:28] SY: Done its job.
[00:06:29] VJ: Yeah. It gives you like this translated version in an executable, and then the compiler is like, “Peace! Here’s your translation.” And that’s like the end product.
[00:06:38] SY: Okay. So then if what I am downloading in my exe is the executable version of the code, does that mean I don’t actually have the source code?
[00:06:49] VJ: Yes, you are right. You actually don’t have the source code. You just have a compiled file. And what’s kind of cool is that I can give you a compiled file and you can run it on your machine theoretically, and you could run it again and again and again with different inputs and you never have to see the source code, which is kind of cool. I can just be like, “I’m not going to show you this, but here’s this executable that you can run. Don’t worry about what was in the source text. Here’s the translation.”
[00:07:16] SY: Yeah, but I guess I don’t really care about the source. You know what I mean? Like ultimately I got to do what I got to do. And if I don’t need the source code and I guess it’s kind of irrelevant.
[00:07:25] VJ: Yes. Yeah. There can be downsides to that and we’ll get to that in a bit, but that’s the TLDR of compilers. That’s basically all they do.
[00:07:32] SY: Okay. That’s pretty straightforward. Our compiler is the only type of translator. I think we’re getting into interpreters.
[00:07:41] VJ: Yes.
[00:07:42] SY: Is that next?
[00:07:42] VJ: Yes. We’re going to get into interpretation. The interpreter is the other kind of translator that we haven’t talked about so far.
[00:07:49] SY: Right. Yeah.
[00:07:49] VJ: And interestingly, the work of building the interpreter couldn’t have happened if someone didn’t create the compiler, and actually pro-tip, shout out to my girl Grace, Grace Hopper.
[00:08:00] SY: My girl! Like you like go hang out at the mall or something.
[00:08:07] VJ: Oh man, I would have loved to.
[00:08:09] SY: That’d be fun.
[00:08:09] VJ: She seemed like such a badass.
[00:08:11] SY: I feel like she’d be a really efficient shopper I think because she was in the military. She’s like a Navy. What was she? No, I made that up.
[00:08:17] VJ: She was like an admiral, I think.
[00:08:19] SY: Admiral, that’s what it was.
[00:08:21] VJ: She had this really illustrious career and like people didn’t believe in her, and she was like, “I don’t need you to believe in me. I’m just going to make this compiler.”
[00:08:28] SY: Like a boss.
[00:08:29] VJ: So she created the compiler in 1952, and quite a few years later after that, the interpreter was created and it was because of her work on the compiler. So I just want to shout that out. And the interpreter is the other kind of translator, and it’s heavily influenced by the early compiler work that Grace Hopper did, but it’s different in what it does when it translates.
[00:08:51] SY: Okay. What’s the difference?
[00:08:53] VJ: So an interpreter doesn’t do all of its work in one fell swoop. So instead, actually, here’s a great way of thinking about it. And interpreter is like, you know the UN when like there’ll be proceedings and like someone’s like translating line by line or like when you go to a conference and there’s like a stenographer who’s literally translating as somebody talks.
[00:09:13] SY: Yes.
[00:09:14] VJ: An interpreter is kind of like that. They’re sort of doing it live.
[00:09:18] SY: Cool.
[00:09:19] VJ: So an interpreter does do something similar to the compiler and that it takes a high level language, which is our source language, source text, and it does convert it into machine code. But it actually runs and executes the code that it translates immediately as it’s translating it. So another term for that is running it in line. And so when the interpreter is translating, it basically translates the source text into a target language one line at a time, and it’s doing it step-by-step. So it’s like, “Okay, read it. Translate it. Here’s the translated version. Okay, now I need to read the source text again. Translate it. Here’s the translated version.” So it’s very systematic in that way.
[00:10:02] SY: So it basically more or less ends up with the same result of translating our human code to machine code, but the way it does it, it’s different and the output is a little bit different too.
[00:10:13] VJ: Exactly. It’s interesting that you mentioned the output because there isn’t really an output in the sense of like an executable or like a file that’s been compiled. That’s not a thing with interpreters because the interpreter is kind of like it’s more committed in a way than the compiler. The compiler is just like, “Look…”
[00:10:36] SY: It’s more faithful.
[00:10:37] VJ: The compiler is like, “Here’s your file. I’m leaving. Bye.” The interpreter sticks around because it has to like actually translate line by line, right? Like if you imagine if the stenographer was just like, “Bye,” in the middle of your talk, then you wouldn’t have any translation left, instead the stenographer stays around and it’s like translating line by line. So in a similar way, the interpreter translates your source code line by line and executes it at the same time. So you don’t need a compiled file. You don’t need an executable. This interpreter is doing it for you, but then the interpreter is sticking around. So that’s like sort of a fundamental difference.
[00:11:13] SY: Does that have an effect on performance of the interpreter versus the compiler?
[00:11:18] VJ: Oh my gosh. You have such a good intuition for compilers and interpreters. You’re asking all the good questions.
[00:11:25] SY: I’m very smart.
[00:11:27] VJ: But yeah, you’re right. It does have an impact on how quickly you can translate that code. So generally speaking, code that is compiled tends to run faster, like it makes sense if you think about it. You’ve done the work of translating the source texts into machine code already before you even tried to execute it. But on the other hand, interpreted code, you are translating it as you go, like sort of life.
[00:11:52] SY: Right. Intuitively, it just felt like it’d be a slower process. Like if I’m cooking and eating together…
[00:12:05] VJ: I’m just imagining you doing that.
[00:12:06] SY: You know what I mean?
[00:12:07] VJ: What does that even look like?
[00:12:08] SY: Well, I mean, if you’re cooking really well, then you can’t help but like sample along the way. And then by the time you’re like done cooking, you’ve also finished eating. You know what I mean?
[00:12:22] VJ: Yeah.
[00:12:23] SY: No?
[00:12:23] VJ: Wait. You and I cook differently. I must be a compiler. I’m like, “Listen, we’re going to make everything and we’re going to sit down and eat.”
[00:12:30] SY: And you don’t taste anything during, you just like you cook it all the way through and then you eat it. But you know what I mean? If you like sampling a little bit here and there.
[00:12:38] VJ: Yeah.
[00:12:38] SY: So I feel like if you cook the way I cook, you’re not really cooking fast or eating fast.
[00:12:44] VJ: Or efficiently.
[00:12:45] SY: You’re not very efficient. Yeah. Because you’re like trying to multitask. You’ve got a little bit of pasta in the potty, a pasta in your mouth, it’s like a whole mess.
[00:12:53] VJ: I have something to say about that process. I would like to point out that if you cook your way where you are checking things as you go, if something goes wrong, you can immediately like figure out what was the thing in the process that went wrong, like where the problem was, right?
[00:13:07] SY: That’s true. That’s true.
[00:13:08] VJ: So if you were like eating pasta and you’re like, “Oh my God! There’s no salt in this sauce,” like you’re like, “Oh, I know exactly where the problem is. It’s the sauce and there’s no salt,” I guess.
[00:13:18] SY: In fact, Chef Gordon Ramsay encourages you to taste. This is really just a cooking show in disguise.
[00:13:27] VJ: We’ve taken a hard turn into the kitchen.
[00:13:33] SY: It encourages you to taste. Why? He says, “Taste everything. Taste everything.” That’s not a British accent. He says, “Taste everything because otherwise you won’t know how well you’ve been seasoning because it’s really hard to just tell the season just from measuring it. You got to taste it along the way.” So Chef Ramsay cooks like I cook. We are interpreters. And that is that.
[00:13:54] VJ: And to bring it back to code for a second, I think you have a really great analogy and like I just want to tie it into what an interpreter would do in terms of interpreting lines of code. There’s like flexibility to an interpreter because if the interpreter is staying around to run the source code, it’s sort of like interactive. And so if, let’s say, there’s an error or something goes wrong, if you’ve written your program well, then maybe you catch the error and you surface it to the programmer. And if you were interpreting line by line, now you’ve made it like a little bit easier to debug what went wrong because you are literally at that point in the translation where something went wrong. On the flip side, like, well, okay, one caveat before I go into the flip side. One caveat here is that you have to actually catch the bug, right? Like you could also have an issue and then it could all explode and then your interpreter wouldn’t know what to do. So that's important to mention. But with a compiler, like let’s say something went wrong in the process, imagine that I just gave you the executable file and it blows up on you. If you don’t have the source code, you might not even know where the issue is because you’ve just got the translated version. So it could be really hard to debug that and figure out what went wrong. If you don’t even have the compiler and now you just have a translation and you’re like, “Oh, okay, now I have to figure out where in these things blew up and I don’t even know how to read this,” it can be tricky, but it is faster.
[00:15:29] SY: Those are some good points. So it feels like if we look at kind of just like the high level differences that we just talked about, we have what gets returned as different, compiler gets an executable, interpreter gets kind of like nothing, like you get like the result of your executed code if there is a result, but that’s kind of it. We talked about compilers, you run it once. Interpreter, you need to run it every single time.
[00:15:49] VJ: Or it’s like constantly running is the way to think about it.
[00:15:51] SY: Constantly. Yes. Every time you need the source code the whole time, it’s committed.
[00:15:56] VJ: Yeah. And if you make a change, it has to run again to pick up on that change and retranslate it.
[00:16:02] SY: It evolves with you and moves with you.
[00:16:04] VJ: That’s deep.
[00:16:04] SY: And then we talked about debugging, how a compiler, you can’t really figure out if anything’s wrong until the very end, but interpreter, you can taste your seasoning along the way. So it sounds like there's just genuinely tradeoffs, right? I guess just like when we put any type of tech tool. There’s always going to be tradeoffs. So I’m wondering, do you have a favorite? Are you a compiler versus an interpreter kind of gal?
[00:16:25] VJ: I really like interpreters for debugging, but I will say this. We talked about high level differences, but there are some compilers that do things really well that interpreters don’t do. Like for example, there’s a language called Rust whose compiler I really find interesting. It basically doesn’t let you compile it into like that source text if you have any bugs and it makes it very, very safe. So like that’s really cool. I like that kind of compiler. And then there’s some interpreters where I’m like, “Oh, this is kind of annoying.” Like you can have bugs at runtime. And then sometimes I’m like, “Oh, this interpreter sucks.” So really it’s just like as you said, it’s the tradeoffs of choosing a language and whatever things you’re trying to do with it, like thinking about what translator is going to come out of the box for you. And like there’s other interesting things about compilers and interpreters in terms of security and like how you’re building for people. So if you use a compiler, then people don’t need the source text, but then you need to make sure that your executable works for everybody. So sometimes you’ll have to be like, “Okay, I have to make sure this works for Windows and Mac and Linux.”
[00:17:33] SY: Right. Right.
[00:17:33] VJ: And with interpreters, you’re not giving somebody an executable, but then you do need to make sure that when someone downloads your interpreter, like the Ruby Interpreter for example, you want to make sure that it works with Windows because that interpreter does only translator. There’s no executable. You’ve got to make sure it works.
[00:17:49] SY: Nothing else. Yeah.
[00:17:49] VJ: So there’s different tradeoffs and they’re both like two different tools for the same job, which is turning human readable code into something that makes sense to your machine, which is a really important job.
[00:18:02] SY: So as developers, do we get to pick if we want to use a compiler or interpreter or does it just generally come with the language that we choose? So you mentioned Rust for example. Is Rust always compiled or is there also a Rust interpreter or how does that work?
[00:18:18] VJ: Yeah, usually when you pick a language, you’re making a de facto decision about whether you’re using an interpreted language or a compiled language.
[00:18:25] SY: Okay.
[00:18:25] VJ: So by choosing the language, you probably want to know whether you’re going with compilation or interpretation. And when you make that decision, you will get one or the other as your translator.
[00:18:37] SY: Okay, cool. And that’s the end of today’s show. If you liked what you heard, please leave us a review and make sure to check out Vaidehi’s blog post. Link to that is in your show notes. I also want to give a huge shout-out to DigitalOcean and Heroku. DigitalOcean is a simple developer-friendly cloud platform, which makes managing and scaling apps easy with an intuitive API, multiple storage options, integrated firewalls, load balancers, and more. There’s also a robust community that provides over 2,000 tutorials to help you stay up to date with the latest open source software, languages, and frameworks. Get started on DigitalOcean for free with a free $100 credit at DO.co/basecs. That’s DO.co/basecs. There’s a reason over nine million apps have been created and ran on Heroku’s cloud service. They not only manage over two million data stores, but they make over 175 add-on services available to you. So whether you’re creating a personal app, a free app, or an enterprise app, start building today with Heroku. This episode was edited and mixed by Levi Sharpe.
[00:19:47] VJ: Bye everyone.
[00:19:48] SY: Thanks for listening. See you next week.
Thank you for supporting the show!