 Whatever programming language you learn, there's a core set of things they virtually all have in common, and I want to lay those things out here as quickly as possible. So, first I understand that in all cases, programming is about data. It's about analyzing data with logic. It's about transforming data with logic, and it's about generating data with logic. That is the essence of every program. And to be a useful program, every program must do what we call output. It must write data outside of itself. It must write data to a file, send data over network, put data on the screen to display, send audio data to an audio device that then gets played out through speakers, etc. These are all forms of output. And if your program doesn't do any output, then it's a useless program because it doesn't have any effect on the world that any human can observe. Programs may also do input. They may read data from outside themselves, such as reading data from a file or reading data from a network or read data from human input devices like mice and keyboards. And most programs do do some input, but it's not strictly necessary the way output is because you could have a program that just simply generates data and outputs it without doing any input. Now, data can come in many different kinds, but the essential kinds, which most of the things are then made of, are numbers, strings, booleans, and collections. Numbers require no explanation, but a string is a piece of text. It's a sequence of text characters, and a boolean is a value that's simply just true or false, which are used to represent all sorts of yes, no pieces of data. Like, for example, is it currently sunny outside? Yes or no? True or false? Lastly, a collection is a piece of data, a value, which is made up of other values, which might be numbers or strings or booleans or even other collections. And there are many different kinds of collections because there are many different ways to organize multiple values, but the most obvious and simplest and probably most commonly used is a simple list. You have a collection, which is just an ordered list of, here's the first thing, here's the second thing, the third, the fourth, the fifth, and so forth. Now, as for actual programming languages, the mechanisms which they virtually all have in common is, firstly, they all have some set of built-in operations, they all have variables, they all allow you to branch with usually what are called if statements, they all allow you your code to loop with what are called usually while or for statements, and then they all have functions, which are basically like operations you yourself define in your code. You have a small set of built-in operations, usually a few dozen, and with a function you essentially can define your own operations. And with just these few mechanisms, you actually have a complete programming language. The question, though, is what about input and output, because none of these mechanisms do either input or output. Well, we'll explain how input and output is done in programming languages when we get to the end. So, operations. Most languages have a few dozen operations, and that will always include arithmetic, some logic operations, and perhaps things for manipulating strings to split them apart and to join them into larger strings, and then a few other odds and ends operators, which differ from language to language. And each of these operations, what they do is they take input values, usually two for most operations, they do something with those input values and return an output value. So, examples include, most obviously, arithmetic, where we say we might add together two numbers, and it returns a number, the sum of those two numbers, where we might multiply two numbers, which then returns the product of those two numbers. But aside from arithmetic operations, we also have some logic operations. What's called the AND operation, for example. We'll check if two Boolean values are both true, and then it returns a Boolean value that's true if they are. Otherwise, it returns a false value. And then what's called the logical OR operation, we'll check if at least one of two Boolean values is true, and it returns true if that's the case. Otherwise, it returns false. There's also an equality test operator that will check if two values are equal and return the Boolean true if that's the case. Otherwise, it returns false. So, say we can check two numbers if they're equal or check if two strings are equal. And lastly, for manipulating strings, very commonly languages will have a concatenation operator, which takes two strings and returns a new third string, which has all the characters of the first combined with the second after it. And be clear that concatenation leaves the two original strings unmodified. It generates a new third string rather than modifying either of the inputs. And this is the case with most operations. Most operations don't manipulate their inputs, they just rather return a new generated value. Now, in our code, we want to be able to store values in memory. And for that, we have what are called variables. The variable is a named location in memory, which stores a value. When you create a variable, you the programmer pick the name of the variable. It can be whatever you want. It can be, say, Tom Dick or Harry or X, Y or Z or whatever. In practice, you should pick good meaningful names that indicate what is being stored in these variables. But whatever the name, having created a variable, you can store a value in it with what's called an assignment. An assignment takes a value and stores it in a variable by overriding whatever was already there. So say in our code, we might create some variable named foo and another variable named bar, and then we can assign the foo the number value three. So we can directly assign new values to variables. What we can also do is take the value of an existing variable and assign it to another variable. So we can say assign to bar the value of foo whatever is currently stored in foo gets copied into the variable bar. And we can also assign to variables the result of operations. Operations return values and those values can then be assigned into variables. So say we can assign to foo the value returned by adding eight and three. So then the value 11 would be copied and stored in the variable foo. Be clear that these variables in programming, they're called variables, but they're not like variables in mathematics. In mathematics, you have variables in equations like y equals 2x in which for all possible values of x, there's a corresponding value of y and vice versa. What we call variables in code, they denote storage locations in memory and at any one time in the course of execution, a variable is storing just one single value. They're called variables, their values vary, because as code executes, we can change what a variable stores, but at any one moment a variable is storing just one value. Now as so far described, our code is just a sequence of statements executed top to bottom, and these statements so far will create variables and assign values to them. Often though, these statements of code, we want to take a chunk of them and have them only execute conditionally. So as code executes from top to bottom, it encounters a block of code, a chunk of statements that it might skip over based upon some condition. And that's called branching. And to do branching, we use what are called if statements. And if statement starts with the word if followed by a condition, which is some Boolean variable or operation that returns a Boolean. And that's followed then by a body contained within the if, and the body is just one or more statements of code. So what happens when our code executes is it goes top to bottom, and when it encounters an if statement, it first evaluates that condition. It looks at the Boolean variable and sees if it's true or false, or it performs the operation and sees if it gives back true or false. And if the condition is true, then the body of the if is executed, but otherwise if it's false, then the body is skipped over. So for example, we might have an if statement where the condition is an equality test between the variable foo and the number value three. And so foo stores the value three at that moment when the test is performed, then it'll return true and the body will be executed, but otherwise the condition returns false and the body is skipped over. For another example, you can have a relational test operation. You can test if the value of variable bar say is less than the value nine, and if so the body of that if will execute, otherwise it'll be skipped over. In addition to branching in code, we often want to be able to loop. We want to have a chunk of code that potentially repeats some number of times. This is done with what's called a while statement, which is actually exactly like an if, but for one difference. Like an if, when the condition of a while tests true, then the body will execute. But unlike an if, after executing the body, execution will jump back and reevaluate the condition. And if the condition is true again, it'll execute the body again. And each time after executing the body in a while, execution jumps and tests the condition again. So as long as that condition keeps testing true, every time execution jumps back to evaluate the condition, the body of the while will keep executing one more time. Only once the condition tests false does execution skip over the body of the while and continue on after. Very importantly, we generally don't want the body of a loop to execute repeatedly forever. We don't want it to be an infinite loop. And so somewhere in the body of the code, it has to somehow change something, usually modify some variable, such that either in the next test of the condition or in some future test of the condition, eventually that will become false. If the condition of a loop never becomes false, then a loop will never end. And that's generally not a good thing. We don't want infinite loops. Last thing to say about loops here is that while statements, because they are kind of statement, they can go in the body of other loops and in fact of other ifs. So you can have loops within loops, loops within ifs, and in fact also ifs within loops and ifs within other ifs. You can just nest them arbitrarily as much as you want. Generally, though, we want to avoid our logic from getting too complicated. So it's generally a problem to have it nested several levels deep. But it is something that languages allow. Lastly, we have functions. A function is a body of code, which we've given a name such that elsewhere in code, if we want to run that body of statements, we can call or invoke the function as we say by name. And in that place where we call the function, the body is executed. In the body, we can do whatever we want. And the function can also return a value to where it is called. With what's called the return statement, we specify what value the function returns. And this return statement can go at the end of the function or actually can go earlier than the end. You might have some branch of code earlier in the function, which if we go down that branch, then we return early from the function rather than completing the rest of the code. Functions can not only return values, they can also take values as input. And this is achieved with what are called parameter variables for the function you specify. If it has zero, one, two, three, however many parameter variables you want. And then when you call the function, you provide an argument of value for each parameter. So for example, if my function foo has two parameters a and b, that means when I call the function, I have to provide two arguments, two values. And the first argument is assigned to the first parameter a, and the second argument is assigned to the second parameter b. And then in the body of the function, I can do whatever I want with those two parameter variables. They're otherwise just ordinary variables, but special about them is how they get their initial value. Anyway, our functions can take input and they can return output. So in a sense they are like operations. A function is like an operation which we ourselves are defining in our code. Languages typically have only a few dozen built-in operations, but we can in a sense extend the set of operations by defining our own functions. In fact, in most languages, a program is effectively a set of functions. Any function can call any other. And there's no code, there are no statements that exist outside of the functions. And program execution begins by calling the function which is given the special name main. So a little strangely, your main function isn't necessarily written first in code, it's not at the top of the file, it could be at the end of the file, and yet that is where execution begins. And then from there, from main, we can call any other function and from those functions call other functions, etc. Be clear that when a function calls another, when main say calls function foo, execution of main is in a sense suspended while foo executes and only once foo returns does main resume execution. Execution picks up from where foo was called and if foo returns a value, that value can be used as an argument to another function call or as an input to an operation or it can be assigned to a variable or in fact you can just ignore it, you can discard the value returned by a call. Lastly about functions, understand that their parameter variables and any other variables created within a function exist only within that call to the function. So I might have two functions which both have a variable named x, but x of one function is a totally separate independent variable from x of the other, they have nothing to do with each other, they just happen to have the same name. Furthermore, when I call a function multiple times, if I call my function foo multiple times, each time it has its own set of its local variables, if it has parameters a, b and c and variables d and e, every time we call foo there's a different a, b, c, d and e. The variable a of one call to foo is a different variable than the one of a different call to foo, they are separate variables. A separate set of the function's variables is created each time the function is called and then that set is destroyed in effect when the call returns. Very last thing, I promised to explain how input and output is performed in code. Well, it's first important to understand that the programs we write are run by an operating system. When your system boots up, the operating system code is loaded and the operating system is responsible for managing the hardware and for managing other running programs. When programs want to read and write data from input and output devices, they're not allowed to do so directly, they have to go through the operating system. And so through some mechanism of the hardware and the operating system, which varies from system to system, but through some special mechanism, usually a particular CPU instruction, programs can invoke system calls, which are requests to the operating system to have the operating system do some kind of input and output on the behalf of the program. So saying my program, if I want to read or write a file, my program can't really do so directly. It has to make a system call to request that the operating system read or write the file on its behalf. So the question is how do we invoke these system calls from our language? And usually the language has no direct mechanism for doing this. There's no code you could write yourself in the language that would invoke a system call. Instead, usually the language provides a set of special functions that are not normal functions of the language. These are functions implemented in a special way that will invoke system calls. And so to invoke system calls, you invoke these special functions.