Computers are very good at following instructions. If you tell a computer to do something,
it will do precisely what you tell it to do, and it will do so without question or
complaint when you have it do the same thing over and over again.
This reliability is key, because it means that programs can be created that
instruct the computer on what to do, and there's an extremely high degree of certainty
(basically 100%) that the computer will do exactly as instructed (though 'bugs' arise
when the computer does as instructed, but those instructions are not what the programmer
intended to give).
Note: All definitions that I use, unless otherwise stated, are my own, and are informal. I think it makes more sense to give a definition that fits in the context of what I'm trying to say than to give a book definition. I may leave out details that I think will cause confusion at this point if I include them, but I will try to make a note when I do so. I may also make some generalizations for the sake of not being overly technical.
I know a lot of you already know what a computer is, but bear with me. I want to go over the basics of what a computer is and what they do, because in order to understand what a program is, it's really helpful to know what programs have to work with.
Computers have a few components:
- Hardware devices
- Central Processing Unit (CPU)
"Memory" refers to a place that data can be stored and retrieved from.
There are two classifications of memory, volatile, and non-volatile.
The difference between the two is in whether or not stored data will be retained when power is lost.
If you've ever experienced the
joys misery of losing your work
when your computer loses power, that's because the main memory (ie Random Access Memory, or RAM)
in your computer is volatile.
If, however, you've ever had your computer lose power and didn't lose your work, either because
you saved your progress or because the program you were using automatically saved it for you,
that's because the data was saved to non-volatile memory, ie your hard drive/SSD.
Yes, your hard drive/SSD is a form of memory, albeit very slow when compared to RAM and registers
on the CPU (more on that below).
A computer is able to control and interact with various hardware devices, such as a display, mouse, keyboard, speakers, WiFi/Bluetooth antennas, cameras, the list goes on and on. The exact details of how this is done is beyond the scope of this post, but suffice it to say that a computer, and thus a program running on the computer, has the ability to interact with these devices.
The most vital part of a computer, as indicated by the name, is the Central Processing Unit (CPU). The CPU performs (or at least initiates and manages) every action on the computer. It does this by executing instructions, one* at a time. Basically every instruction operates on data in one form or another; in order to work with said data, the CPU must first load that data into extremely fast memory devices called registers.
A computer has a limited set of instructions that it understands, and these instructions are very basic. Broadly speaking, there are the following types of instructions that a computer understands:
- Instructions to perform basic math and calculations
- Instructions that compare values
- Instructions that store and load data
- Instructions to control hardware
- Instructions that change what instruction will be performed next
From these limited instructions, programs can be created.
A program is some combination of instructions and data that, when executed, does something. That statement is deliberately vague because, just as you can fling paint onto a wall instead of using a brush or roller (or some other piece of painting equipment), so too can you put instructions together randomly and create a 'program', though you're extremely unlikely to end up with anything meaningful. From here on out though, let's use the following, more restrictive, definition: A program defines operations that a computer should perform; a program is created with a particular intent, to accomplish a particular task or get a particular result. A program thus has a higher-level meaning that provides context to the instructions being executed.
Though all programs ultimately boil down to different combinations of the same low-level instructions, not all programs have to be created directly from those instructions (and in fact very few programs are nowadays). These low-level programs are written in assembly language; the term low-level is used because assembly language is basically a one-to-one mapping of one line of code to one single instruction that the CPU will execute. However, assembly programs are very cumbersome and take a long time to write, so over time programs were created in assembly that could read in a file that contained code in a higher-level language**, parse the described program, and generate another program. These programs are called compilers.
I keep mentioning "higher-level" languages, but what does that mean? And what's a language? A programming language is a lot like human language -- there's syntax (grammatical structure), words that have special meaning (called keywords), and a general flow or order. Programming languages allow a programmer to express programs in a human-readable form, which is eventually translated into a form that computers understand. Different programming languages have different syntaxes, but every programming language exists in order to enable a programmer to do "stuff".
Now, when programming in assembly (which is as low-level as it gets), there aren't explicit notions
of things such as loops (executing a set of instructions repeatedly) or functions (a named set of instructions
that can be re-used), or even the notion of assigning a name to a particular piece of data.
Other languages, though, that have these notions, can be compiled into assembly.
These languages allow programmers to express the intent of their code much more easily.
Generally, the more high-level a language is (not that there's really an absolute scale), the
easier it becomes to develop programs that do more in fewer lines of code.
Higher level languages abstract many things away so that the programmer
can focus on the task at hand, instead of getting caught up in implementation details.
Note: I don't want you to get the wrong impression about assembly; anything that a computer does, any program that runs on your computer, can be created in assembly. It's just a matter of how long it takes to write, and how difficult it is to maintain, because the programmer must keep track of many, many things which, in other languages, they don't have to.
Now that we've established that there are "higher-level" languages, and that they make it easier for programmers to write programs, it's time to go over the core components that programs are made of, and that programmers have to work with. I have written dedicated posts about each of these (except Data Structures and Variables, which I combined into one post). Follow the "Suggested Next Reading" links at the bottom of each post to go from one post to the next.
- Primitive data types
- Data structures
- Conditional statements
First, a word on "data types". In the real world, everything gets classified: "that thing is a tree", "Fido is a dog", "I am a person". These classifications make it easier to manage the world. If I say "Sam is a dog", then you will have certain expectations about what attributes Sam has: an age, a name, eye color, a breed, etc; you will also know that when someone says "Sam, speak!" they are giving Sam a command to bark. If, though, I say that "Sam is a car", those expectations will change: Sam will still have an age, and possibly a name, but it won't be an eye color but a paint color, and instead of a breed Sam has a make and model; if someone says "Sam, speak!" you will likely be confused, because cars don't speak (unless you're in an animated movie).
Similarly, when programming, it makes it much easier if one assigns meaning to data by saying that it's a particular type. It's a little abstract right now, but once I get to data structures and variables this should make more sense. Note, though, that just as there is nothing about the individual atoms and molecules that make up Sam that distinctly identify Sam as being a car or a dog, there is no intrinsic quality or property of data that determines what type it is. In some programming languages, if you try to reference a Dog as if it was a Car, it would be an error to do so, because the programming language tries to ensure you are writing valid code; in others, however, the language would not prevent you from doing so (though unless you know what you're doing, your code probably won't function, and is likely to crash).
*Modern CPUs actually run more than one instruction at a time, but that is
beyond the scope of this post.
**A compiler translates a program written in one language into a program written in another language. There is no requirement that one program be "higher level" than the other.