 Since you've come across this video, I assume you want to learn AIDA programming. Now, whether you're a completely new programmer or somebody who already knows programming but doesn't know AIDA yet and need to for whatever reason, I got you covered. I've been programming in AIDA for about 12 years now. I know the language pretty well at this point and something I've noticed over the years and even from my own experience with learning is there's not a lot in terms of the resources available. There are some good books, but books really aren't for everybody. So in this video, we're going to be covering AIDA, its history, its purpose, as well as a lot of the language features. Nothing is going to get covered in great detail, but by the end of this video, you will be left knowing how to do many common tasks in the language. You will be able to read source code that is out in the wild and actually understand it. After this, I will be doing more specific videos on specific topics. Those will be what you want to cover to really understand a specific part of the language, but you will wind up knowing the language after the end of this. So for the overview of the language, let's begin with its purpose. The US military was at a point using a wide variety of languages. Many of them you probably never even heard of, even if you've been programming for a decade or two. Obviously, it's very hard to keep a staff who knows how to use all those languages, and so they began an effort to consolidate that down. Now, there were a bunch of language revisions going from, I believe it started with the straw man, then wood man, tin man, iron man, and then steel man language requirements, but basically what they wanted to see in a language, what they felt it should have. And the military, obviously this is going to be focused on embedded in real time systems because missile systems, tanks, all that kind of stuff is controlled by software. And you really don't want these things to fail. So a lot of the focus, a lot of the language requirements that they were focused on were about making the code as safe as possible, as error resistant as possible. So never get bug free code unless the program is super trivial, but you can make steps to make it less buggy. And so as a result, a lot of common uses of AIDA are with avionics, like the, I believe it's the Boeing 747 is programmed almost entirely in AIDA, but it's not the only jet that is done that way. These kind of things aren't always publicly available, but there are quite a bit of jets that are known to be programmed partially or overwhelmingly in AIDA. Also railways, this can be either like standard trains or subways. One big example of this is the Paris Metro banking. This is one where we don't really have a ton of information, compiler vendors like Atacor and now PTC know that they're selling the commercially supported compilers to banks, but they're not super open about which ones. And obviously the military and anybody who makes things for the military is going to wind up using AIDA at some point. Now for a while with the military, there was a hard requirement for a few select languages that's been loosened up, but Atacor is still used a lot there. And space technology, parts of the ISS are programmed in AIDA. There was a satellite, the CubeSat project, which was programmed almost entirely in AIDA. I believe there was a bit of a similar scene along with that, but a huge portion of it was done in AIDA. And so like most languages, it's gone through a bunch of versions or revisions. The original AIDA, the one that was really just focused on military embedded purposes, was AIDA 83. This was the one that actually was part of the design competition the US Department of Defense engaged in. Back then it was known as green before it was selected. This was led by a small team led by Gianni Faya. Essentially, the steelman documents, the language requirements that the Department of Defense put forward, they had a bunch of teams competing to who could sort of best implement a language that could meet those requirements. Other than the language requirements, the Department of Defense didn't have a whole lot of say in the language itself. It was just a bunch of people competing, but it goes forward. Gianni Faya's team was the one who won. And like I said, this pretty much only targeted embedded in real time systems. It was overwhelmingly just a military focused language. But there were some really good things about the language. And so it was revised in a way that expanded it greatly for other purposes. This would be what I consider the first version of AIDA that's useful for anything other than just embedded in real time programming. The first general purpose version of AIDA. And this was led by a small team. This was done by a small team led by Tucker Taft. This was revised again in 2004, 2005, which added some more advanced features on top of the language and revised again for 2012, adding even more advanced features. Now, it's sort of an ugly part of languages that need to be covered because this is a thing in your experience developer. You know what I'm talking about here. But every language has dialects, slight differences. And you see this with spoken languages as well. There's differences between the United States and Canadian English. There's considerably bigger differences between English and the Northern Atlantic versus English, the UK or Australia. This happens with programming languages, too. Microsoft's Visual C implementation is different than the NGNUGC's C implementation. This was something that they tried to nip in the butt with AIDA. And as a result, there's almost no dialects. I say almost because there are some slight differences. But the AIDA language requirements are very strictly defined and help to ensure very consistent behavior and ensure that everything is very well-defined and predictable. Essentially, the differences that occur between different implementations of the AIDA language are with some slight features that you can often ignore or work around very easily. In practice, you will not have much trouble moving from one compiler to another. Now, there is the Ravenscar profile, which is not so much a dialect, but more like a limited version of AIDA. Reduce a lot of the additional stuff. And it's meant for using, like, AIDA 95 through 2012 in embedded environments still. And you also have Spark, which is sort of a subset, sort of a superset of the language. I'm not going to delve too much into that because in its own right, it should get its own video. Even still, Spark is pretty well-defined. So if you have one compiler vendor that implements Spark and another that implements Spark, chances are everything will work cleanly between them, too. And Spark was even designed in such a way that its additions would not cause it to fail, a compilation to fail on a compiler that did not implement Spark. So as for the typing discipline, AIDA is very statically typed. So that is, when you declare a variable, and we'll get into that in just a little bit, whatever type it's assigned to will not change. So if you say that you have a variable A and that it's an integer, it will always be an integer for the lifetime of that variable. You will not be able to say, hey, it's actually now a person for whatever reason. You can't do that. This is sometimes considered inflexible, but does help a lot when it comes to code safety and ensuring correct behavior. Now, it's also very strongly typed. That really has to go along with the static typing. But when you say that it is a person, you can't then take something that's a similar to a person, but not quite and assign it to it. And specifically, it uses what's known as nominative typing. So we'll see this a little bit when we get into records or which are basically structures. Even if a type is structurally compatible, so that is, it shares the same record layout and everything, you cannot assign it to a value of a different type with the same layout if the name is different. Essentially putting higher emphasis on the name that if it's named different, it's probably a different thing and should be incompatible. Now, of course, there are ways of converting what you do actually need to do that. That's the approach it takes. So some criticisms of the language because I'm a firm believer that there's nothing perfect out there. In fact, I also program quite extensively with C sharp because it doesn't do everything well. Major criticism, especially in its introduction, was that it was overly complex. And one thing to keep in mind is this was at a time where a lot of the popular programming languages were things like C and Algol and Fortran. And those are very simple languages, remarkably simple compared to what's commonly used nowadays. And so, you know, it does have a huge specification. I just said it is very complex. It's very sophisticated. There's a lot in the language. There's a lot we need to go through in this video. And well, that huge specification is really nice in that everything is very thoroughly defined and there's tons of things built right into the language that you don't need third party support for. It does mean that there is a lot to cover for the language, that there's a lot a compiler vendor needs to implement, that there's a lot you need to learn to be a good at a programmer. It's a valid criticism. It's also a valid compliment. It all depends on what you're trying to do. If you're implementing some trivial little program, I would really not recommend Ida. If you're implementing something that just needs to do a little bit of automation like a script, Ida is really bad for that. But if you're designing a whole control system, well, that's more what it's made for. Another criticism is that there's too many types. This is like anything. Yes, there are a lot of types in Ida, especially with these characters and strings and will that definitely make a point of that, because there are a lot of different strings. Now, in practice, you're probably only going to use one or two of these. I promise the overwhelming majority of these are for edge cases that you will not need to touch. So while it looks remarkably complex on paper, because it is, in practice, it's much simpler. And when we get to the string specifically, I will make a point of which you want to use where and some recommendations on what you stick with. Another criticism, which is also sort of a compliment as well, it depends what you're doing, is that there's many integrated features. And this does contribute to the amount of overhead when it comes to learning the actual language itself. But tasking is a great example of this. Tasking is how Ida handles concurrency or threads or parallelism. That is built right into the language, which, of course, means that there's an additional language feature you need to know, but then you don't need to grab a third party library to get tasking, you know, you don't need to pull in like a p-threads library with C or C++, it's right in the language, whether that's a good thing or not is debatable. Many, but not all modern languages have this as a built-in thing. C-Sharp is a great example of that with Async, totally different model, but still built right into the language. And there's also a massive runtime library compared to its introduction. Nowadays, when you look at things like the absolutely massive Java library or the absolutely massive C-Sharp library, Ida doesn't look too big anymore. Ida looks pretty normal now, but at least at its introduction, Ida had an insanely large runtime library. Another criticism is that it's overly strict, and I'm not even going to pretend it's not. It is, it's a good thing, it's a bad thing, it's going to drive you nuts. It'll also help you not drive you nuts because it'll catch a lot of bugs. It's one of those things that, like, when it does good, you don't notice it. It's a very strict language, though. This criticism, however, I will not partially agree with or even wholly agree with, that it was designed by committee. And I think this was a huge misconception dealing with the government influence. When it came to the different language requirement documents from the Department of Defense, I'm sure those were designed by committee. It was the government, but if it wasn't designed by committee, then there's something else weird going on with the design process that probably shouldn't happen. But when it comes to the language itself, green, and then when it was renamed to Ida, it was a small team that created the language itself and a small team that revised the language that's not designed by committee. Forget and write a road on my own slides. Well, they're mostly here just to keep me on track anyways, but yeah. So now let's actually get into the language because that's why you're really here, right? Start with the standard hello world. Now, of course, we'll get into all the different components of this, but I would just want to give you an idea of what this is like. This was interestingly considered rather verbose for its time when you look at, say, like the C implementation of hello world, there's definitely less actual writing going on nowadays, though, with object oriented programming becoming so incredibly popular, you can see hello worlds that are quite a bit bigger than this, because you have to write out a namespace and then a class inside that and then the actual main method. Whereas with Ida, you can get away with a program with just the main method, but then, you know, like functional programming and the scripting languages, this is pretty verbose compared to those. So Ida sort of has a middle ground when it comes to verbosity, which is interesting. It didn't historically, but nowadays it's a pretty middle ground. One interesting thing about Ida is there's actually two different ways to write out a program, and I'm not going to delve into when you want to use each of these, but one way, as you saw with the hello world, is that you can write it out as a procedure, which doesn't actually return anything to the runtime, so that is the operating system doesn't actually get a return value, unless there are certain instances where it has to, like on Unix, and then it'll either get a zero or a one, depending on if an exception is raised, but basically you use a program where you don't, when you don't care about returning a specific return value. So like if you're on Windows, you probably want to stick with just procedures, same with, I believe VMS works that way as well, but you can also write it as function, and while it is possible to return other things than an integer in a program, you probably want to stick with just the integer, and that's when you care about return codes, which is especially important when working on Unix. So you can't build everything into a language, and you need includes in some way, so that you can say, hey, this is the other thing, I need this. That's done with a with statement, so it's just with and then whatever the name of the package you need is. One important thing to keep in mind is that unlike some other languages that are a little bit more succinct about this, just withing a package does not immediately scope to that. That is, when you with it, you still have to write out the full name of the package and then everything that you're using within the package. To avoid that, you can wind up using a use statement with the same name, and that scopes to it so that you can no longer need to use the full name. Now I'll go more in depth in this into another video so that you can get a good idea of how scoping invisibility actually works in Ida, because it is actually pretty different from other common languages, despite using a lot of the same terms. So especially if you're coming from another language, you really need to brush up on some of those differences. Oh, as for assignment, you know, I talked about variables earlier and that I was going to delve a bit into this. Now we're beginning that something you'll notice here is that in the declare part of this function, there's the A, which is an integer and a B, which is a constant integer by default variables. Well, by default, a value is a variable so we can do things like assign a new value to A. And this is actually done inside the actual execution part of this function, but it is possible to declare constants by just prefixing a constant, but like literally constant in front of the type name. If you try to assign B a new value, it will fail. But if you try to assign A a new value, it will work. Now attributes, this is again something that will get its own more dedicated video, but attributes are really sort of an odd thing that Ada has that pretty much no other language has. And you'll see attribute used in like to describe something in other languages. C sharp has this with the attribute classes that you can attach to other classes, which change some little things about the class. That's not at all like they are in Ada, but they're presented like this with an apostrophe and then the name of the attribute. And they're generally like information about an object or a type. They're somewhat like an intrinsic function, which is something that's automatically defined by the compiler. It's not something that needs to be provided by the by another library. But they're also somewhat like reflection. And like I said, this will be something that gets covered in other videos because it's a subject very unique to Ada, so it needs to be covered. When you have pragmas and aspects, now, pragmas are something that pretty much every language has in some form. In Ada, they're presented rather obviously as just pragma and then whatever the pragma name is. Now, some of these accept options, which then cause them to look a bit like a function, but they're all presented in that general way with pragma and then the name aspects. On the other hand, immediately after whatever the aspect is applied to, you have with and then the name. Now, there are many pragmas and aspects that share names, generally speaking, with Ada 2012, where they were introduced, instead of the pragma, they have you using the aspects instead. But this isn't always the case. And both of them are director directives, which control the compiler. They're a way of providing additional information about things. And with that in mind, aspects, especially, are pretty similar to the C-sharp attributes. They're also used for contracts. If you've ever used a language that supports contracts, Eiffel, I believe, is one of these. They're preconditions, post-conditions, and a few other things that help assert how the function or procedure or whatever it is is supposed to behave. And they're also used for restrictions, which is a way of limiting how many features the Ada Runtime Library is actually providing for your code. That is a way of eliminating unnecessary cruft. Like if your program doesn't actually use tasking, why bring in all the tasking overhead? You can restrict that out. And it does wind up sometimes providing some performance improvements, sometimes just cutting out some of the fat. So we have the operators, some of the logical operators, if not A, A and B, A and then B. Now, this is important because in a lot of languages, the logical and as well, the logical or, short circuit by default. In Ada, the default, I guess, the most straightforward writing one, actually evaluates both sides, even if you already know the end result. With that in mind, I would strongly recommend using the short circuit forms unless you absolutely know you need to evaluate both sides. Overwhelming majority of the time, you should not need to. So just stick with short circuit form until you find out you need to use the standard form. Then we also have the XOR operator with an actual word name and not some weird symbol, which I kind of like that. So relational operators, these are all pretty straightforward. The one thing you will notice is that with the equal to operator, it's just a single equal sign. It's not the double equal sign that a lot of languages use. And that's because assignment has its own operator. Operator, we'll get to that. Arithmetic, all pretty straightforward. One thing that is worth pointing out is there is an actual exponentiation operator. So I know that's sort of something that drives me nuts when I program with C sharp is you have to call math.pow and then the stuff. There's an actual operator you can use with string concatenation. I really enjoy that this uses a different operator so that it's clear when you're doing addition and clear when you're doing concatenation. If you've ever done JavaScript programming and have intermixed strings and numbers, trying to concatenate them and getting weird results, you know exactly what I'm talking about and why I appreciate this. Now, this is something I don't want to say unique to IEA, but definitely not something seen in most other languages, at least that I've encountered, but there's actual membership operators. And so that's to test whether something exists in a set or container. So for some examples, because I know this isn't super obvious, we can do a range membership test with checking if five is within the range of one to 10. And of course it is, so that would evaluate to true. Another one where we tested five is in an integer. Now, this is a tight membership because integer is tight. And so what this actually does is uses the range of the type to essentially perform a range membership test just using the name instead. Now, five is yes, an integer, so that would evaluate to true. But then we can also do class membership tests. Now, if you know what object oriented programming is, then you understand what this is. If you don't, I'll cover it in object oriented programming more specifically, but. Well, actually, I'll have an example when we cover tag types, which is part of how I had to implement object oriented programming. It'll we'll cover that then. So an assignment, I want to make a point that this is not actually an operator in EIDA. Assignment works very differently in EIDA than in some other languages. And that will also deserve its own video because it actually gets rather complex. But I'll do a whole deep dive on how assignment works in EIDA and why I think it works really well. That I think it's the right approach. And I think it says a lot that C sharp is actually shifting over to try to get as close to possible as how it actually does assignment. So some numbers. Most of this will be pretty straightforward if you already know programming integer types. You can decal. Actually, before I forget, in EIDA, you can declare new types. Now, there are a few other languages that can actually do this. Ida is definitely one of the few where you can declare new base types. This isn't always useful. Don't declare your new type just because you feel like it. Generally, stick as much as possible with the standard types. But if you do need to enforce a specific range for whatever reason, or any other property about the type, you do actually have a mechanism to do that. But for an integer, it's just a range. Obviously, it's going to be whole numbers. Modulars are sometimes mistaken for unsigned numbers because they sort of are unsigned numbers. But the way modular arithmetic works is that when you reach the highest value and you increment one more, it wraps all the way around. This might sound a little bit weird, but it's actually something that you've seen throughout your life. Clocks work this way, where you go from 1 o'clock, 2 o'clock, 3 o'clock, all the way around to 11 o'clock, 12 o'clock, 1 o'clock. Now, generally speaking with programming, and this is definitely how it works with Ida, you actually start from zero and then wrap around at the modulus. So using the clock analogy be 0 o'clock, 1 o'clock, 2 o'clock, all the way around, to 10 o'clock, 11 o'clock, 0 o'clock. Floating points, if you don't know programming, it's scientific notation, basically. If you do know programming, you could probably understand why the ability to declare new floating point types is really, really, really nice in Ida. I don't know if you can do the really small, like, I think it's a eight-bit float, the graphics cards use. I don't know if you can do that in Ida, but you can actually access a wide variety of floating point types with different precision and everything in Ida. It's super handy. And yes, if you're on an X86 or AMD 64, whatever you want to call a different variations of it, you can get the 80-bit floating point in Ida. You can totally get that. It's actually the default long, long float on that platform. Now, fixed point, generally speaking, these are being phased out because floating point performance is actually really good now. It didn't used to be, but they're pretty close to on par nowadays. Now, Ida separates this out into two different floating point types with the ordinary and decimal. Ordinary is essentially a binary representation of it, the ordinary for the computer, not for you, but for the computer, it's ordinary. If you need decimal precision or radix precision, but it's the fractional part of it, but you can't use a floating point type, maybe the ordinary fixed point type will fit your needs. Decimal, on the other hand, is really what you want to use for financial systems. There's something called floating point rounding error. If you happen to be involved in fintech at all, you know what I'm talking about, and you're probably giddy as shit looking at the ability to define your own decimal types because, oh my God, this is amazing for financial systems, and you can probably not at all surprised to see that banks buy out of compilers now. Now another similar basic type is enumerations, and they look like this. You can specify any number of values, and it is actually possible to do layout type stuff so that if you're doing bit flags, it is actually possible to implement this fairly easily, in Ida. They're pretty simple types. There's not really a whole lot to discuss with this. Enumerations work the exact same way in Ida. Well, pretty much the exact same way in Ida as they do in other languages. There isn't a whole lot of differences that really need to be covered. You'll figure that out totally fine if you're already programmed. Arrays definitely deserve some unique discussion. So here in this example, we have, be honest, I'm not sure if that's actually valid, a thing. I wrote it in there just for the sake of succinctness, but I don't think you can actually do anonymous arrays. I may be wrong. Some of my knowledge goes from very old versions of Ida that this may be a thing now, but the point here is just to get you familiar with how arrays look and everything. Arrays in Ida, you can actually specify the index. Now this has to be done with any discrete type and that basically means any enumeration, integer or modular. In this case, we use a subtype of an integer, positives, because it's a little bit cleaner, saner, less error prone. If you index the array from one to whatever size it is, in this case, it would be one, two, five. That helps something called a one off or off by one error that happens a lot with indexing in Ida. But it is worth noting that you can index with any range. So I could actually specify after the positive a range of like negative 27 to negative 22. This seems weird. It's rarely used, but especially when doing hardware interfacing can be extremely useful because you can map that to specific ports on like a controller's interface. Then after this, we specify the type the array is actually of and this can basically be anything. If it's a definable type, you can have an array of it. And then you actually assign the array. After this, in the actual execution part of the function, you can see how indexing works, pass the index in to parentheses. Ida uses parentheses for pretty much everything. I don't really like it. I'd like to have unique actual symbols for that, but that's what they decided to do. Arrays can also be done with comprehensions, though. Very limited support for comprehensions, but there are comprehensions. And the only one it implements is a step comprehension, which is still useful to have, though. So in this case, it's done by declaring two initial values and then the actual rest of the range. In this case, because it's two and four, what it does is finds the step between them and then applies the step the entire way to the end of the range. So this array would be the same as the previous two, four, six, eight and 10 because of the step of two. You cannot declare more complicated steps. Like, it can't be a step of two, then three, then four. It has to be just a simple step. Now matrices or multidimensional arrays are pretty straightforward as well. You just declare another additional index. And it is actually possible to intermix the indexes. This is done when defining tables, which are similar layout-wise to a matrix, but very different conceptually, where you might have one of the index would be a number while the other index would be a character, like an Excel spreadsheet, basically. And here we actually have a matrix that's using comprehensions. Now you can only use comprehensions for the absolute innermost array. You can't use them for the top level arrays, as far as I know, anyways. And indexing, of course, is done very similarly to defining them. You just pass in the two different values. Strengths. Said we were gonna cover this, giving you an idea of what's actually useful, what you will actually encounter regularly with strings and explain what all that other crap was. So strings are an array, and of course then you have to ask of what. They're an array of character, but there's also many types of characters, less so than strings, though. But there are several different characters we need to touch on. And so as a result of there being many characters, there's also many types of strings. So let's cover the character first. It's a special type of enumeration and represents all of the different characters, code points, glyphs that make up text. And so there's three types of characters that need to be considered. The character, a wide character, and a wide, wide character. Let's go back to that. So I'll just say first, unless you're working in an embedded environment, you wanna use wide, wide character because wide, wide character supports the entire Unicode range. All of the Unicode code points are supported if you use wide, wide character. The only times you want to use the smaller ones, like character or wide character, is like I had said, with embedded systems where reducing the amount of code points you can actually represent saves space. Otherwise, just stick with wide, wide. So then with that covered, let's get back into strings and actually explain all this. So I had said it's an array and it corresponds very simply. For characters, the equivalent array is a string. For wide characters, it's wide string and for wide, wide characters, it's wide, wide string. But there are different types or variations of this string. You fix it, bound it, superbound it, and unbound it. And what the heck are these? For fixed, it's just the one known as the string or wide string or sewn. It must have an assigned size because it's like any other array. So if you have a string of 10 characters, so the index is one through 10, it must always have 10 characters. You can assign it a new value, but that new value must be 10 characters long. This probably seems very unflexible and it is, it is. This was chosen as the default behavior for the strings going back to as initial introduction as an embedded focused language. This does happen to be really good for performance reasons. And so even though there's more like developer friendly strings available, the base string, the fixed string is still what's often used for text IO purposes just because it is fast. It's a very, very efficient representation for text. Bounded is a bit more flexible and this is most of the time what you want to use when interfacing with databases. So it's in a similar vein known as a bounded string or a bounded wide string and so on. It must have an assigned size and that size can be calculated at runtime like you saw with the array and with the string. But it may be a smaller size. It does a little bit of a padding trick to hold it in a string while wrapping up the expected behavior. So if you say it's originally 10 characters long, then you can never assign it a string of longer than 10 characters, but you can assign it shorter ones. That, if you've worked with databases, you'll know that that's the default behavior for text and databases and that's what makes this good for interfacing with databases, that you can have the same behavior in your add a code as your database actually has. Superbounded, I'm just gonna breeze through this but basically it's just a special version of bounded. If you need to know which to use when ask me to cover it, I'll do a video of it. I don't have one planned just because this really isn't touched very often. Unbounded is where we get into the strings that you want to use if you're not doing embedded programming or database programming. If you're doing anything else, so this means most developers you want to use the unbounded string and this because it's the most flexible. So similarly with the other ones, it's known as unbounded string or unbounded wide string and so on. There's no assigned size so this allows it to actually be a smaller size or a larger size. If you define it as a string of 10 characters long, you can then go and assign it with a string of 143 characters long and then one of two characters long. It's very flexible like that. So it's actually implemented as a container of sorts, not an array, although it can actually be done as a sizeable array which is, don't want to get into that but just know that it is actually very flexible. This also does mean it's extremely slow. Now I'm saying extremely slow relative to a normal string in Ida. It's performance really isn't that bad. If you're trying to squeeze as much performance as possible out of your code, feel sorry for you but this is going to be something you'd want to look into then but if you're using this, you're probably doing a lot of heavy text I have stuff anyways and your input output is going to be far slower than the strings actually are. These, absolutely what you want to use in the majority of cases. They're actually more flexible than strings in other languages. They're lovely. So sub programs because Ida actually has a different, quite a few of these and it's not like, it's not like in C where they're all functions and you have void return value which makes it kind of like a procedure but it's not the same thing or not like object-oriented languages where they're all methods. There's actually a few of these going on. So the procedure, this is going to look similar again because it's what you saw with the actual, with the actual implementing programs. It's one of the ways to implement a program. You will notice here, just to help you get at least somewhat familiar with attributes, we actually have the image attribute and this is where you see a little bit of this sort of reflection-like behavior going on. The integer image attribute gets the, what the integer looks like string-wise, character-wise. This is often called like a two-string method in languages that have to rely on that. But it's done as an attribute in that. So this isn't something that you need to define or anything like that, it just exists. Function, very similarly, has an actual return value and so you need to return that somewhere within the code. In this instance, we have a very simple one which just immediately returns value after doing a slight computation. Because that's such a common thing to do with functions, you also have what's known as a function expression and doing that same code before as a function expression, it looks like this, which is now actually just a one-liner. A lot simpler to write. And we have operator. This is done as a function and yes, that actually supports operator overloading. Only for its defined types, you cannot define new, or only for its defined operators. You cannot define new operators, but you can use any of the already defined operators like the add or the and or absolute value or anything like that to define a new operator. And this is one of the important things about noting that assignment is not an operator. There's other implications behind that as well, but it does mean that you can't use operator overloading to define new assignment behavior. Now, in this specific example, I don't have anything actually written because for the add operator, because it's already intrinsic for integer, there's no way to actually do anything here. It would actually be assembly code, but it's just providing for you. But I just wrote this out here so that you could see how operator defining is actually done. I shouldn't have wrote an example at the end. That's my bad. That's what I get for copying slides and then editing them. But it's done by instead of a name, just putting the operator in double quotes. You still call it like normal though. And it's also worth noting that it's possible in edit to write the sub-programs, whether it's a procedure or a function or even an operator as a generic. And that's done with this generic prefix on top of the actual definition. So in this instance, we define it as having a generic integer type parameter that gets used and operated upon. And here you can see how it's actually instantiated. We give it a new name of integer double and just perform the instantiation afterwards. Now, integer double can be called anywhere after this and operates upon integers. So now conditionals, because programming isn't that useful if you're doing just one thing after another with no considerations. The most basic AFLs. So you can see that we test if a value is greater than zero, we return true, otherwise we return false. And this just works out as a simple positivity test. AFLs, AFLs, just a slight expansion upon the AFLs. And I haven't just saying a bunch of goofy stuff, but you can see how multiple checks are done within the same AFLs block. Now case statements, this is usually called switch in a lot of other languages. There's a slight little bit of syntactic difference between the two. So you can see that it's introduced by a case instead of a switch and that the individual parts of it are done as a when with whatever the condition is rather than a case. Different cases can be combined by putting a bar between them. And what would be called a default for switch case blocks is just done as a when others. And you have exit when. Now this only applies for inside of loops but is a way to exit a loop, a little bit of syntactic sugar for exiting a loop rather than doing a if test and then exit. So here we have what would otherwise be an infinite loop just constantly incrementing the integer. But we have a very succinct test for if the I is five, then just exit the loop. So this no longer becomes an infinite loop. Now there's a bunch of different loop syntaxes we'll get to in just a little bit but this is a rather convenient way of putting exit conditions anywhere within the loop. And it is actually possible to have multiple exit statements within a loop, multiple exit when conditions. So let's get into loops. We have the standard loop, just an infinite loop. One that literally does nothing but it is an infinite loop. So if you were to run this program, it would never stop. It would also never do anything but it would never stop. You have a while loop, pretty standard thing for other programming languages. So tests for a condition as long as that conditions evaluates to true, it executes the loop. If the value is not true, if the value winds up not being true at the very beginning, then it doesn't execute the loop at all. Then we have a foreign loop. So this sort of takes advantage of the range membership test. So as long as I is within the range of whatever you specify the floor and ceiling is, it will execute the loop. Otherwise, it goes to the end of it. And in this case, there's nothing else to do. So it's done the program. You also have a for each loop. Also sometimes called an iterator. We'll just skip ahead there. You can see an attribute is being used again. In this case, the range attribute gets the full range of, well, an array in this instance. So this array being what the step of one to three up to 100 should have, I think, 50 values. So the range would wind up being one to 50. Then you have packages. Packages are for the most part, out as way of packaging up other values, other functions, other procedures, into reusable components. With that in mind, they're kind of similar to static classes from C sharp of Java, kind of similar to modules from Visual Basic. I don't really want to give analogies to something like Python or Ruby because I'm not super familiar with those languages. And reusable components in JavaScript is really complicated. So I'm not going to give an analogy to that either. Packages come in two parts in Ida. You have a package spec, which goes in one file. And it looks something like this, where you have a package followed by its name is, and then it stops at the end followed by the name. The private part is optional, but know that if you don't include it, that everything within the package is publicly visible. I'll touch on this a little bit for here, although there's going to be a deeper dive into this, where you can see some more advanced stuff about packages and explain how this works. But private in Ida doesn't mean the same thing as private in, say, C or C sharp or Java. Private is not visible by packages that use this package or anything that uses this package. So if I have another package or a program that depends on example, I will not be able to call anything within the private part. But a child package of example, like example.child will use really simple naming. You can actually see everything within private. So with that in mind, it's kind of more like internal, but even still there are differences. But then the other part of the package you have is the package body. And this goes in another separate file. And this is where you have all the implementations for everything that was declared in the spec. If you need something that is private in the sense of the C languages, you put it in here. Because then not only is something that depends on example, not able to see it, not able to use it, but even child packages are not able to interact with it. And then one little note just so that you'll be aware that this is a thing and that packages aren't quite just like static classes or modules or that kind of stuff is that they can actually have initialization code, which is like a constructor. And that is weird coming from other languages. I'm not going to get into explaining this and why it exists and how to use it. Just know that if you see that in somebody else's code, you're not losing your mind. That is valid code. It's not often done, but it does have purposes. And like I said, there'll be a video covering this in great detail so that you understand packages better, especially this whole initializer constructor thing. And much like the subroutines, packages can also be generic. And it's implemented the exact same way. Before the package, you put the generic and then whatever the generic parameters are. With generic packages, what winds up happening is anything inside of it at all is initialized all at once. So if you need to initialize a large collection of functions or procedures all for the same type, you probably want to use a package rather than a bunch of generic functions and procedures all laid out. Not always, but that's probably the route you're going to want to take. And exactly like with the generic subroutines, they're initialized the same way, the new name of it, and then the actual initializer. Now, records or structs. These are one of the first more sophisticated types in that it's not just a simple one-value type. Records hold multiple values together. If you've worked with database programming, you should recognize why they're called records. There's a pretty strong mapping between the two, actually. It is database friendly, which is sort of weird to think about. But it gets a little bit complicated with its records. There's a lot going on with them. And this makes them quite a bit more powerful than structs in a lot of other languages. One of the first differences, variations of records you can have is the discriminated record, which for the most part is going to look basically the same. But you'll notice that there is actually a size parameter property that's in a weird place. Now, you can still access size like any other property, but it's placed immediately after the type name. And when you declare values of this type, of this example record, if you have an E of example record, you need to put in the size as well. Sometimes this is used just as like a mandatory initial value that needs to be sent. But it can be used to modify other values, other other, I'm saying value because that's what it's called here, but other properties within the record, other fields, other entries, whatever you want to refer to them as. In this instance, the actual length of value, because remember strings are arrays, they have to have a defined size. And since we're not assigning it, it can't determine the size. So you need to tell it the size. In this instance, we're actually telling it the size in the discriminator. This actually goes even further to create a variant record. And this is going to take a little bit for this, because it's actually got to write quite a bit of stuff out. But you can see we have the discriminant just like before. But then something very unlike what you see in almost any other language, where we have actual logic inside of the record. Now I have a bunch of entries where nothing's really all that different. We have a seeds property and the doors property. And there's a bunch of these entries where it gets considerably different is with the pickup where it has another additional property. So if you were to say vehicle is specifically the option of a sedan and you try to access the towing capacity property of that, it would fail, because it literally does not exist in that record. But if you create another vehicle with a pickup as the option, you actually have the towing capacity property to get to. This should kind of seem like a class inheritance hierarchy polymorphism thing that you'd see from object oriented programming. And it essentially is a more limited form of that. Now there are other uses for this other than just the object oriented light stuff. But if you're interested in object oriented programming and have a very simple hierarchy going on, you might want to consider a variant record instead. But I do have some content about explaining these in more detail and giving examples of how these are actually used and when you want this versus actual object orientation. So we have the tag record, which as I had said earlier is part of how Ida implements object oriented programming. Ida takes a different approach from a lot of popular object oriented programming languages in that it doesn't force everything altogether. There's not a class type that has all of the components of object oriented programming walked into one. You can actually select different parts of it and, of course, even combine all of it for a true OOP experience. Tag records are just a record that has an associated tag or like a V table if you're coming from C++. It's information about the dispatching. OOP is sort of a complicated subject to explain in detail. But it allows you to do things like what's demonstrated here. And this is where we'll actually cover a little bit about class membership. So we have a person record. It has an associated tag and for the person they have a defined name and age. We also have a defined procedure which renames them. Then we have another tag record, this time a programmer that inherits from person. So that is programmer has everything that the person actually has as well. So the programmer has an actual name and age property that you can get. You can also call rename on a programmer and it works. Programmer has an additional string array of known languages. Now, string array isn't a default type, but you get the idea this is showing up tag records more than being valid code. And it also has a defined procedure for learning a new language, which you'd expect would add a new language to the array. Learn language cannot be called on a person, but as I had said, rename can be called on a person or a programmer. And then to explain a little bit about how class membership works, if we have a very me and it's a person, I can say me and a person class and it will evaluate to true because of course I am. But if I try to do something like me and programmer class, it will fail. Now, obviously, that's a little bit nonsensical. I should probably be defined as a programmer, but in this instance, I decided not to. This is because I am specifically in this case defined as a programmer as a person, not as the programmer which inherits from it. Working the other way around now, I can have say another variable, John, who is defined as a programmer. John in person class will evaluate to true because programmer happens to inherit from person. John in programmer class will also work in this instance, and will also evaluate to true because yes, he's actually specifically the programmer. And then just something to consider is that record types can be combined, so it is possible to have a variant tagged record. This might seem a little bit redundant, but there are actually uses for it. It's rare, but there are uses for it. And so record is a type like any other, and so you can have a record which includes another record. And just a little quote because I happened to actually find this very important and useful thing to program by. Is get your data structures correct first and the rest of the program will write itself. David Jones. So now let's cover interfaces. These work the same as any other language that has interfaces. And basically it's a way of saying for a tag type, things that it needs to implement. It doesn't provide an implementation for them. Just says that anything that implements this interface will have these different properties, or different functions and procedures rather. So to use the classes we had last time, if we have a programmer that happens to inherit from person and I example, which we have here, then programmer should also be expected to have a do something procedure. Now, whatever it does is, I don't know, but it will need to be implemented by whoever, by whatever, rather uses this, utilizes this interface. Getting ahead of myself that, you know, what I just said. And just to cover some of the little differences in interfaces, because there are different interfaces. I realized I didn't touch on this with the records. A record can be declared limited as well. It has specific meaning. This slide should not exist here, but it has specific meaning when involving assignment. Assignment, a record being limited, changes how assignment works and whether it's possible in certain situations. Limited interfaces can only be applied to limited types. Then we have synchronized interfaces. I realize we haven't touched on these yet, but this applies to tasks and protected types. We'll touch on those and should be coming up. I don't know if it's right after this, but it should be coming up somewhere in here. And then you have task and protected interfaces, which are just more specific versions of the synchronized. So if you have an interface that can be applied to either a task or a protected type, you'll want to use synchronized. If it should only be on one of those, you can use the specific task or protected. So access types are sort of how EIDA handles pointers. If we have a type that we want to access, we'll just give another example, integer. The access looks like this. Now you can have anything defined as an integer access and it accesses the integer. What this means is a complicated subject. As a new programmer, you can sort of view it as that a value assigned to the access is just like the value itself. There are actually some important differences, but when reading code, when learning the language, you can view it like that. It'll at least get you through understanding how the code works. So some things to note about access types is that they are not a pointer, not quite anyways. Sure, they do point to something, but they definitely don't work the same way as pointers. There isn't any pointer arithmetic stuff going on. Now it is possible to actually get that through a specific type that exists in EIDA, but we're not gonna cover that here. And with this in mind, it's much closer to a reference, although it's still not quite that either, but it is probably best to view it as a reference. Now it refers to another thing rather than actually being that thing. And exceptions, because EIDA does, and pretty much has always had built-in support for exceptions. Classic example of one, divide by zero. You can't do it. So if we attempt to do it, the handler goes after whatever the code execution is. So this makes it a little bit different from try catch blocks, where instead of wrapping a specific portion, we just have the entire exception handling at the very end. And this looks basically the same way as a case statement, and can largely be viewed the same way as a case statement. You can even group multiple exceptions together with the bar between them. I'm not showing that off here, but that is how you do it. And for the default, just like with cases, it's when others. So if we run this code with a divisor of zero, of course, it's going to throw a divide by zero exception, which we catch and print out the line, one cannot divide by zero. Concurrency, this is where we cover the tasks and protected types. I'm not gonna get into this in great detail, just some basic introduction to the stuff. So you have tasks, task types, and protected types. And yeah, these are getting covered in another video, just know that they're a thing. So hopefully this leaves you at least familiar with the language. You should be able to read Ida code that exists out there now, even write some basic programs in Ida. I'm currently in the process of redoing a lot of videos. If you happen to have come across my channel before, you've probably seen this content already, just it was kind of crap when I originally did it. And I'm trying to get all this stuff done better. So a lot of the other videos that came after the initial ad introduction and adabasics video, which got combined into here, are getting redone, hopefully much better. Let me know how this video is. I'd really like to hear, so I know how I've come, how I've improved from when I started, because it was not. But I'm also continuously looking to improve, to get these videos better. And I'd really like your feedback. With that in mind, also because of how YouTube ranks videos and helps people find videos and everything, please consider giving this a thumbs up. That's one of the best things you can do to help more people be able to find this video and learn about adab, learn how to get familiar with the language. I have a good one.