You may have heard that programming languages such as Ruby and Python and Java are “higher-level languages” — whereas languages like C and Go are “lower level”. What does this mean?
Having a higher or lower level does in fact have a specific meaning. It’s more than just a way of saying “I like this more” or “this language is easier to program in.” The “level” in question is the level of abstraction — how far abstracted the language is from the underlying hardware.
Underneath everything else, a computer is a machine that encodes 1s and 0s as pulses of low or high voltage electricity running through transistors. This is a very messy reality, and there’s tons of details and strange quirks that go into how exactly a computer is put together. For instance — just to pick one example — there are dedicated circuits for doing certain types of math, like arithmetic, but they only work for certain size numbers, so you have to handle bigger numbers seperately.
A very low level language is one that deals directly with this underlying reality. Their vocabularies match the circuits: you can talk about the specific CPU operations your computer is actually doing. Languages at this level are generally called assembly languages.
A language like C is higher level than assembly language. It lets you play a game of make-believe, by creating an abstraction of an imaginary computer that’s much simpler than actual computers. For instance, in the imaginary C computer, you can tell it to define a function that takes an input and gives you an output, and then use that function elsewhere in your code. A “function” is just a C abstraction — the actual computer hardware has no idea what a function is. Behind the scenes, the C compiler is translating your functions into assembly language, but you don’t need to know that to use them — you can pretend that the reality that C shows you is the actual reality. It’s kind of like the Matrix.
So is it better to write in C or assembly? It depends on what you’re trying to do. C can let you pretend that computers are nice and simple, but every once in a while it’s useful to know what’s actually going on. For instance, if you’re trying to harness the very last ounce of speed for an extremely demanding high-def video game, sometimes going down to the level of assembly lets you pull off tricks you just can’t do in C. But for most of the world, most of the time, C’s reality is fine. And if you’re working in C, you can get work done much, much faster than assembly, because you can forget about all the messy details of how computers actually work.
This is great and that’s why those languages are popular for building things on the web – because when you are building an app, you don’t usually need the level of control that C gives you over memory allocation, and you save a lot of time by not worrying about it. However, in our opinion, those languages are still too low-level for optimal web programming. If you’re building a web app with a Ruby backend, you have to worry about, among other things: sending data from the server to the client, talking to a database, the way web browsers translate html and css into your user interface, asynchronous vs synchronous event code, and much more.
This means that you can do more with less time, because instead of focusing on lower-level details that aren’t important to what you’re working on, you can focus on creating an amazing app.