 In programming, paradigm refers to a fundamental approach, a style, of considering and solving problems. Most programming follows either an imperative paradigm or alternatively a functional paradigm, and at the same time most programming follows either a procedural paradigm or alternatively an object-oriented paradigm. So, like with static versus dynamic typing and weak versus strong typing, we have four combinations – imperative and procedural, imperative and object-oriented, functional and procedural, or functional and object-oriented. The distinction between the imperative and functional paradigms is that, in the functional paradigm, you're not supposed to modify state. It's called functional programming not because it has a monopoly on functions, imperative programming has functions too, it's just that functions in the functional paradigm are meant to conform to functions in the pure mathematical sense. In mathematics, a function strictly defined is meant to be adempotent, meaning that no matter when a function is called or how many times, that function should always return the same value for a given set of arguments. For example, a function foo, called with the argument 5, should always return the same value no matter how many times we call the function or when. Moreover, a function in the pure mathematical sense produces a return value but otherwise has no effect on the world outside it. In functional programming, each function is meant to be a pure black box that takes input and returns output, but otherwise has no other contact with anything outside itself, such that a function called does not affect, and is not affected by, the outside world. And be clear that the outside world includes not just the objects and variables outside the function, but also any input and output devices or data storage, such as a console or a file. Now, the obvious problem with the functional ideal is that programs only do useful work by reading and writing data outside themselves, in other words by modifying state. You can write a brilliant program which competes the meaning of life, but if the program doesn't display the meaning of life on a screen, or write it to a file, or send it across a network connection, or just in some way get the data to the world outside the program, then it doesn't matter that we've computed the secret of life, the secret will just sit there in the program memory, and when the program terminates it will just disappear. So, the very thing which the functional ideal prohibits, talking to the outside world, are programs need to do in one way or another. In truth then, what the functional paradigm is really about is minimizing state change by confining it to subsections of a program. The cost of doing this can be quite high, as confining state change is a tricky thing to do, but the benefit is that the purely functional portions of your code will be easier to understand, modify, and correct. Having now defined the functional paradigm, we can easily define the imperative paradigm as the opposite style, the style of programming in which we do not attempt to confine state change. As you might guess, the imperative paradigm is the default style used in the large majority of code, as it's simply the more straightforward way of getting work done. The simplest way to think of the distinction between procedural programming and object-oriented programming is that in the procedural style we think in terms of action before data, whereas in the object-oriented style we think in terms of data before action. When programming in the procedural style, a programmer thinks first of what functions they need, and then secondarily thinks about the data types those functions will operate upon. In contrast, when programming in the object-oriented style, the programmer thinks first of what data types they need, and then secondarily thinks about the functions to operate upon those data types. This inversion of priorities may sound like just doing the same work out of order, but as we'll discuss in the video about object-oriented programming, the styles really do produce different program structures. So, given our two pairs of paradigms, we have four possible combinations. Imperative procedural programming, imperative object-oriented programming, functional procedural programming, and functional object-oriented programming. While imperative programming is much more popular than functional programming, procedural programming and object-oriented programming are perhaps about evenly popular. I would say imperative object-oriented code is most common today, but imperative procedural code follows close behind. The rules of a language we call it syntax and semantics. Synthetical rules concern the arrangement of the code text, whereas semantic rules concern the meaning behind that text. In practice, though, learning to program in a language is about more than its rules. You must also familiarize yourself with its libraries and learn the essential associated tools. A library in programming is a body of pre-existing code. In practice, when we write a program, we don't want to have to write everything from scratch, so we often use library code for common functionality. For instance, most programs do something with files, and it would be silly if we had to write all the code ourselves to open and write files. Using a library, we should be able to read and write files by simply invoking a few pre-existing functions provided for us. Most languages have what is called a standard library, or core library, meaning a set of library code that comes stock as part of the language. In the C language, for example, your C compiler should come with the C standard libraries. For functionality not covered by the standard library, we can often use other libraries. While some of these libraries may require licensing fees, many free open-source libraries are very popular for all sorts of functionality. The term tool in programming generically refers to any sort of program which programmers use to develop software. At a minimum, you'll need a text editor to write your source code, and a compiler or interpreter to run your source code. While basic usage of these tools is generally straightforward, they typically have many complex advanced features. While the choice of compiler or interpreter is, of course, language specific, you can generally write code for any language with your favorite text editor. Some programmers prefer basic editors like Windows Notepad, but others prefer very complicated editors like Emacs or VI, both of which have very steep learning curves. A debugger is a program that helps programmers track down the cause of bugs by executing code step-by-step while reporting what's happening in the program memory. A profiler is a program that helps programmers optimize their code by measuring the performance of code. By identifying the bottlenecks in their code, programmers can better optimize by focusing their optimizations on the right parts. A version control system helps programmers manage their files of code as they create and modify them over time. The basic idea is that the programmer can store a snapshot of the current state of their code in what's called a repository, such that at any future point, the programmer can later retrieve this version of their code. These version control systems also greatly help teams of developers coordinate their changes to code. Lastly, an IDE, an integrated developer environment, is basically a program which combines all or some of this functionality into one program. Arguably, IDs are just elaborate text editors with conveniences, such as hotkeys for running your compiler or debugger. While some programmers swear by their favorite IDE, other programmers insist on keeping their tools separate.