 So, let's talk sub-programs. Similar to encapsulation, some of the terms here are not remarkably strictly defined, so you will see a little bit of variancy, but these are definitely more better defined than for encapsulation, so you'll be able to get rather concrete definitions here. I'll even point out a few of the slight differences between languages. So, the purpose of sub-programs or sub-routines is code reuse. Before, you used to do way, way back with assembly, maybe even some of the early programming languages, just a series of operations and any time you needed to do something over and over again, you just wrote that same thing again. That's bad for a lot of reasons. You're increasing the total amount of code. If you have to change that sub-program, then you have to change it in every single place there, so this helps implement code reuse. And also separation of concerns in that you can break each little thing into its own function, so that each, so that you have one function or procedure, whatever, one sub-routine doing one thing. So as for the function, this is generally a named always. This is always a named sub-program, and it generally accepts zero or more parameters. It always returns a value. And this is just my recommendation, but that they are best used for calculating something. So think math functions. Don't think going off to the internet, making a database connection to some remote database, grabbing stuff back. Think mathematics calculation type stuff, for logic calculations, not operations. That's a bad example. Not performing a task, just calculations. And these are typically, at least I find, but also preferably pure. That refers to function purity, that a function does not have side effects. So try not to alter the environment or have the environment affect the outcome of a function. I strongly recommend that functions are kept pure, even in languages that do not force function purity. If you go through, like, my own mathematics libraries, you'll find that everything is pure. But then we have a procedure. This is also a named sub-program, and it generally accepts zero or more parameters. Unlike the function, it does not return anything as a return value, but in many languages, Ida included, there are in and out parameters. So it may return stuff through the parameters, but not actually the return value. So how do I describe this? We'll get to it with the later bullet points. So again, in my recommendation, these are best used for performing a task or modifying something. And there's generally no need to be pure. In fact, these kinds of things often wind up modifying the environment. There is ways to do things like text input output or other types of human interaction with functional environments, where through the use of monads and similar. But some people, myself included, find it easier to do this type of stuff with procedures, leaving the pure functional stuff to functions. And in languages that only have a function keyword, like C, a function that returns void is essentially a procedure because nothing's actually being returned. Note that a function that returns null is not the same thing. That would be an ordinary function under the definitions that I am providing here. Then we have the functor. This is essentially the same as a function because it's just a special type of function. You see these in very functional languages as one of, not one of, as the higher order function. And so we're constraining the definition of the original function just a little bit here in that there's going to be one or more parameters, not zero or more. And at least one of those parameters is going to be another sub-program. That sub-program is known as a callback. And then for the callback, it's a sub-program passed to another sub-program. So the calling sub-program is known as a functor or higher order function. The sub-program being passed into the functor is the callback. And the functor may optionally pass arguments through. And how that's done is the functor takes the sub-program and also the arguments to pass. And then inside of the functor, it's calling the sub-program with those same arguments. Alternatively, a functor may not ask for those arguments at all and just pass them in inside the functor body without the, based on like certain constants or maybe environmental settings or similar. The operator, this one should be pretty intuitive for anyone who's sat through math class and can remember that they're called operators. It's basically just like a function except that the name is a symbol specifically and that they're often called as infix or prefix operators. Infix would be between the two operands. Prefix would be before the single operand. So an example of an infix operator would be like addition or subtraction where an example of a prefix operator would be something like negation or absolute value. And operators accept one or two values. Mostly there are ternary operators such as the FDNL shorthand in the overwhelming majority of languages. However, these only accept one or two parameters. And being a function, they do return a value. And they're used the same way as in mathematics. I mentioned that before. Then we have the method. This is a named sub-program again. And implicitly has the parent object as a parameter. Now, I say this as a general rule. There are languages that it's not implicit that you do have to explicitly pass it. It is a good example of that. However, in most object-oriented languages where you see methods, they're class-based. Most object-oriented languages are class-based. And so the parent object is implicit in calling those because you do the name of the parent object, dot, and then the method name, and then pass any additional parameters. So these may accept zero or more additional parameters. Technically, the parent object is always a parameter, so you sort of can never have zero parameters for a method. But they're generally not actually viewed that way. They're generally viewed as whatever additional parameters they have. Because the whole point of methods is supposed to be message passing. And so the object is just sort of implicit in that. And these may return something. Essentially, a method can be viewed as a function or a procedure that is bound to an object. And one of my recommendations is that these are best used for manipulating the object. But if you're doing something else like just calculating a value or performing some task that is not specifically about an object, you really want to be using a function or a procedure. But that's just my recommendation. And so methods, ideally, you want them pure in the environmental sense in that they don't modify anything about the outside environment, but that they may manipulate or change the parent object. This is just an ideal. This isn't always possible. And in some cases, people still try to maintain functional purity for methods, where they'll return an entirely new object instead of just altering the object. So then accessor and mutator, also sometimes known as getter and setter. These are also named sub-programs in many cases where the language has specific support for these. C-sharp is a good example of that. These share the same name and just behave slightly differently. So these are essentially a method, and as such, they do implicitly have the parent object as a parameter, just like a method does. The accessor accepts no additional parameters. There is a special type of accessor we'll get to later. That does have a parameter. And then mutators accepts one additional parameter. In some cases, like C-sharp, hide this a little bit in that they provide some nice, definitely nice, syntactic sugar for it, where the accessor and mutator essentially look like a value. And operating upon it as if it were a value calls the accessor a mutator. But like with the mutator, calling it as the value and then assigning it, calling the C-sharp treats that as an operator. So the assignment operator and then the value is really identical to the calling the mutator method with the value that you're assigning it. As one of the parameters of the method. It just provides some really nice, syntactic sugar on top of that. And these are used to safely manipulate the values inside of an object or in certain cases to calculate values without storing them. For example, you have a list, which is a dynamic data structure, so getting the length of it is not as straightforward as getting a length of an array. If you're not storing and keeping track of the length of the list within the list object itself, say for slight space efficiency reasons, you might define a length accessor, no mutator because that would be bad, but a length accessor that goes through counts all of the nodes and then returns the value, as if that value was always there, even though it wasn't. Now, I don't think if there's any more bullet points here, but when I mentioned getter and setter before, those are usually in reference to the getter and setter patterns. I'm not sure about Java in recent years, but at least from what I'm familiar with, Java has no support for accessors and mutators within the language itself. And rather, people resorted to a pattern, two patterns, of getter and setter, where the getter is a function that would typically be called get and then the variable name, or value name, and that function would return the internal value. Whereas the mutator would be a procedure, as we're defining them here, they're all methods in Java, called set and then the value, and would accept one parameter of the value you want to set it to. IDA does a similar thing, where I have seen some people use the get and set prefixes. Usually what I see is just straight up the value name, and otherwise follows that pattern to a T. So yes, these are very common in object-oriented programming, basically because they are methods, but there's not a hard requirement that these things be methods in the strictest sense, they sort of are. But sometimes you may have, say like a private record, you know, a record that you can't see all the values in publicly, because you don't want people to change them, but you still want people to be able to see the values within them, and defining them as constant might not always be possible. So what you'll do is define the whole record as private and then have accessors for all of those. Now since it's just a record, not a tagged record, not an object, that wouldn't make it a method, but for all intents and purposes that's still an accessor. So then the indexer, I mentioned that there was a sort of exception to the accessor that actually accepts a parameter, and that's the indexer. This is often an implicitly named sub-program, although it doesn't always have an implicit name. And in most cases when calling it, you don't even use the name at all, it's just like however you do an index call in that language. But that's in most cases. My memory serves me right. VisualBasic.net is an exception to this. But like any method, an indexer basically being a special accessor, which is a special method, will have the implicit parent object as a parameter. So then it has one or more additional parameters where all of the additional parameters are indexes of the value that you want to return. That's why it's a special getter. It is getting something, a special accessor, it is getting, accessing something within the object, but it actually has parameters this time. And so these are used most of the time to treat complicated data structures like a list or a tree, superficially like an array, where you can get the values out of it using the array index syntax, even though it's not an array. And then we have the constructor. This is essentially a special function and it, hence the name, it constructs a new object. Now, I'm using object a little loose there. I'm not using it in the very strict object-oriented sense. I mean it as any type of data structure. There are constructors for just like records or structs. Sometimes they may have implicit parameters. They may have less parameters than the record or struct actually has values within it. And so some of those may be implicit depending on the constructor being called, or it may use a few of the parameters that are defined to calculate the rest of the parameters so that you only have to enter a few of them and not all of them and hope they're also correct. But the whole point of a constructor is to construct some type of data structure. And these, I say often, share the name of the object definition. This is a thing from class-based languages where it will share the name of the class. This is not always the case. Languages that do not rely on classes for object orientation like EDA, but definitely others can name their constructor basically anything. And you can use those different names to imply different construction methods and other stuff. But that's it. I hope you found this video helpful. If you have, please give me a thumbs up. If you like what I do in general and want to see more, consider subscribing. Maybe even hit that little bell that gives you notifications when I do post a video. Have a good one.