Swift is a popular programming language often used for creating iOS apps this is the perfect course for learning Swift vandad teaches this course he currently works as a lead iOS Developer and he's created many popular courses hi everyone and welcome to this course my name is vandon and I'm a senior full stack developer from Sweden in this course we're going to talk about Swift as a programming language without blending in Mac OS or iOS or back-end development we're going to talk about variables constants structures enums classes you name it even modern futures of Swift as a program language such as async and await I've been doing iOS development myself since late 2007 and I've been using Swift since 2014 when it came out first publicly this course is built for people who are already familiar with another program language from before you don't have to be very proficient in that language that you're using but as long as you know the basics it could be python typescript JavaScript rust whatever it is but as long as you're familiar with the basics then you should be good to go this video itself is part of a bigger playlist which is available on my YouTube channel and which you can find just by searching for my name and this playlist which I'm referring to is called Full stack with Swift and the goal of the playlist is just to get us familiar with doing Swift development for both front and and back end so if throughout this course I sometimes make references to this playlist then at least you know what that is for before we get started I'd really also appreciate it if you could give me a follow on YouTube just by searching for my name the link to which you can find in the description at the bottom of this video and I'm also very active on Twitter and Linkedin daily by publishing tips and tricks about programming languages and just generally informing the public about languages such as python typescript JavaScript rust Swift you name it so without further Ado let's just get started with the course hi everyone and welcome to this chapter of full stack with Swift in this chapter we're going to look at all the modern Concepts that are available in Swift as a programming language if you've already watched an introduction you probably know that and that this course generally not just this chapter but this course generally is not for absolute beginners so I expect you to already know another programming language it doesn't it doesn't really matter what it is it can be python rust it can be typescript JavaScript whatever as long as you know the basics of programming languages such as what functions and variables are then you're good to go if you don't have that experience from before this course generally might be a little bit difficult for you to follow through with and I will do my best to explain everything but since I I don't really want to explain all the basics um I think it is best that you perhaps have a look at some guides on getting started with another broken language such as Python and then get started with this course however if you haven't worked with any other program language from before and you're also very talented as well and which I assume every everybody is you might be able to follow along with this course without problem so what we're gonna do now is to go ahead and set up a playground basically a workspace with many playgrounds in it and playgrounds are Swift's concept of being immediate being able to immediately see what your changes are doing and it will allow you to basically run your code automatically as soon as you make any changes to your code so it is a very powerful way of testing code or even creating some projects in it you can you can create a whole project with a playground and see the results graphically even on the screen so it's very very um powerful for those of you who are familiar for instance with flutter and dart you already know that you can see your changes and display it on the screen immediately and playgrounds are no different they're very similar actually to how Dart and flutter work but a little bit actually simpler I would say because we're writing pure code and just seeing pure text displayed on the screen as a result of for instance calling a function so in order to continue with this chapter you probably need a a Macintosh um however what we're going to do we're just going to use Swift foundation and SDK in here or a library so you can actually follow through as well on Linux such as if you have for instance Visual Studio code re setup and if in and you've installed Swift you should be able to follow through the only difference will be that those of you who have a Macintosh and xcode installed you will be able to create a simple playground and see your changes immediately for those of you who are following this on Linux and visual studio code for instance you need to run the code manually so you will need to just type your code and then call Swift compiler from from your terminal and we're a console in order to run those codes so it shouldn't be that different so you should be able to follow along even on a Linux machine so without further Ado let's just go ahead and create our workspace now I'll explain what a workspace really is a workspace is a collection of pro projects you could say a collection of files and projects it's it's really just one file that explains the structure of a project to xcode if you're if you're running things on Linux so you don't have to create a workspace you probably can't because xcode does that and unfortunately this xcode um obviously xcode application creates like a proprietary format for all of its files kind of so not the text files but like the workspace and project files they are proprietary XML format which is puzzling Y in this day and age it has to use XML really but um that's a different subject so if you're following through and with the course at home with Linux then you don't have to create this workspace but if you're at home with a Macintosh you need to go ahead and create this workspace together with me so I'm going to bring up my extra just enough in here so that we can see what we're doing I'm going to go to new and let's just say workspace then in here let's just say Swift and crash course YouTube okay in here and let's just say save this workspace as you can see it's just an empty workspace at the moment so it doesn't have any contents what we're going to do then let's just increase the size of this so it takes the entire screen and then we're going to go ahead in file new and then we're going to go into a file and in here type playground in the search field and add a new blank playground okay so the first concept that we're going to talk about in here is going to be called variables so let's just say variables and I can see that our workspace was actually just creating here without any folder so we might be able to remedy that before we click create our playground let me just go ahead and open a finder window in here so let's just go ahead in here you don't see actually what I'm doing but right here is the folder then I'm going to take a I'm going to create a folder in here let's let's say Swift crash course YouTube and place this and and then we can close our xcode place the workspace in there and let's just double click on the workspace to open our xcode so now all the playgrounds that we're going to create are going to be creating inside that folder okay so let's go ahead and create our variables for a playground from scratch so file new file okay and then in here we're going to say playground and you can actually find playground a little bit lower in here I think as somewhere in here you can see in the playground section so let's say blank playground and let's call the variables okay because we're going to talk about variables now so this is the default thing that you can see in here and basically this is your view you might see A Whiter screen in here simply because well maybe you haven't changed your themes in xcode and that's something that you can figure out on your own how to change themes and exit we're not going to talk about that okay let's clear this and instead of importing UI kit we're going to just import foundation and if you're watching this course at home or wherever you're watching this on Linux for instance then and if you don't have a Mac OS you need to also do the same thing just import Foundation just create a simple Swift file you don't have to create a playground just click create a plain text Dot Swift file and then import Foundation library in here okay foreign foundation and Foundation includes all the basic as its name indicates it includes all the basics of what Swift contains really like how strings work how integers work all the default operations between these different variables and even optionals Etc so importing foundations is one of the most important uh things you can do basically in your Swift file as you're as you're getting to learn Swift okay so let's go ahead and talk about variables in Swift There are two different syntaxes or keywords for creating variables One is using a let and the other is creating a variable using VAR so let and VAR the difference between these is very confusing for some people and that they think that let creates immutability and VAR creates a mutability however the only thing different between these two is that a let variable cannot be assigned to again whereas a VAR can be assigned to again and there are some other small differences between them such I mean we will actually look at those things and when we're working with classes for instance or structures how they differ from each other and but for now just know that let's cannot be assigned to again and far can be assigned to a game but also keep in mind that there are some other small differences between them which we'll explain okay so let's go ahead in here and say let's my name and then we say equal to Lambda for instance and then we say let your name is Foo okay after you've done these and created these two variables you cannot assign to them again simply because there are less variables so let's say my name is your name and if we go down here at the bottom of the screen you can see my mouse and I'm going to hold on this button so I'm just going to press my track path and then say automatically run and this will just ensure that this playground will be automatically executed anytime we change anything in it okay you can see the error it says that cannot assign the value my name is a let constant so that's how you know that you cannot assign to it again after creating a let constant you just need to leave it you don't have to you you can't basically assign a new value to it okay so that's how let's works now let's go ahead and create a variable so for now we're just going to create a simple array and already assume that you know what arrays are but we're going to talk about collections a little bit later just know that in Swift you create an array with this syntax with square brackets okay so let's say VAR names is we're going to say Mining and your name okay so we just created an array in here and you can then see the results to the right hand side you can see this array contains van Dot and a foo okay now you can go ahead then and say since this is a variable then it can be mutated even internally if it contains for instance a structure so we say names and then we can call an append function on it and we say bar and then we can also add baths to it as you can see in here so by the end of this then our array called names contains found.foobar and bass however if you change this to a let you will see that we'll get some errors in here saying that this is a let constant cannot use mutating member on immutable value names now this goes to this goes a little bit deeper in how let's mvar are different from each other but in order to understand that we need to understand what structures are because arrays in Swift by default are structures if you're not using old Objective C arrays for instance so just know that by creating a variable array you can append to it and you can remove stuff from it for instance as we'll see later however if this is let you cannot mutate even the internal values inside it so you can see there are two mutability concepts in in Swift one is that you can actually mutate this array for instance you can say names is completely equal to another variable like the law okay so you can see all of a sudden it became blah blah bar bass you see so this is mutating the variable itself it is actually assigned a complete new array to names as a variable and these two statements are mutating what is inside this variable so doing a let in here prevents both assigning a new value to names and also mutating names however having a VAR you can assign a new variable two names and you can also mutate names internally okay so this is another difference between let and VAR so it is also very very important to understand these two differences mutation of the variable internally and assigning a new value to the variable to mutate it so a lot of developers struggle with that especially in the beginning so I completely understand if it is a little bit difficult to start with but the earlier you learn this concept the better because otherwise I think a swift can become quite difficult for for you to understand going forward so spend some time and experiment with a let's and VAR but we will have quite a lot of examples in this chapter so you don't have to do it on your own okay so now if you change a variable like if you've created a variable and you assign a new value to it and it won't it won't change the object that it originally was assigned to now I will explain what that actually means so let's say let's Foo let's create another space in here let's say Foo is foop and then we say VAR Foo 2 is equal to foop like this okay you can see now this variable of food 2 contains the value inside Foo all right and you can see both of them contain the string Foo now if you go ahead and set the value of Foo 2 to for instance Foo 2 like this you can see that Foo and futu still contain the values that you'd expect Foo contains food and food 2 contains the new value so by assigning a new value to Food 2 which was previously equal to Foo you're not overwriting the value that was inside Foo simply because this is referring to this and the reasoning behind this is that we're working with something called value types now I will explain more value types later but all you need to know for now is that by assigning the value of Foo to Foo to we're simply copying this value over to futu so this value is being completely copied and you're creating a new instance of it inside food too so now we have two Foos inside memory by this point so we're not getting a reference so it's not a reference type that we're talking about Swift has value types and reference reference types for those of you who are not familiar with this concept from before don't worry about it I'll explain it more in details but for those of you who are familiar with this concept just know that structures which are basic basically as Swift string is a type of structure it in structures are basically value types and then we also have classes and which are reference types and we'll explain all of these later in the future but just know that by assigning a value that was assigned to a variable would let assigning it to a variable like this with VAR and then changing the value of that variable and assigning a new value to that variable you're not changing the value that was assigned to that variable initially I know that I mean this the sentence is a little bit complicated but I think I think you get my points in here what I'm trying to say okay now we can have a look at another example of this and how that looks so let's go ahead and say let's more names and let's create an array in here and then we say Foo and then a bar okay then let's let's say we create a copy of it we say a copy is more names and simply because this is a let's variable and also that we're working with a swift array which is a structure then we should know that structures are value types and assigning the value of a structure to another let's variable in here creates a copy of this entire array for us okay so now that we have sorry let's make this a copy variable basically let's now go and add some value to this cop a copied variable and say append and we say Bas all right and then we say let's get the value of more names and then the copy you can see more names in here still contains Foo and bar which were the original values however they copied the variable now contains bass as you can see in here so adding Beth to this copy did not change the values that were inside more names and this again goes back to how swift is working with value types in here it is copying over the contents of more names into this copy variable and changing this variable's internal data does not affect the original data which it was assigned to in the beginning okay so hopefully that makes sense by now now one thing that can be a little bit confusing for developers is when when they're working with let M VAR but with old Objective C classes all right and this this can be a little bit strange to start with like a lot of developers who are not so familiar with swift would say that let creates immutable variables so you cannot change them internally however if you're working with a let's variable with a let constant for instance in Swift however that that its internal value is an instance of a class that class can mutate internally without this letter variable getting in the way let's have a look at an example for those of you who are familiar with Objective C you know that there is a class inside Swift which is called NS mutable array now if you just want to learn Swift you don't at all need to know about this it is simply for those of you who are a little bit curious about let's and VAR okay I'm just going to demonstrate this to you but please if you're not completely understanding this example it is completely fine chances are if you're working with Swift and you're learning Swift swift UI and even if you're working with UI kit for instance you create your UI applications for iOS Mac OS whatever chances are you may not really be using the this uh thing that I'm gonna show you at all or maybe you'll use it once or twice in your entire career and more and more Swift gets modern less and less we're going to use these classes so but for those of you who are Mac Developers for instance you probably actually work with NS Mutual array perhaps often okay if you especially if you have an old code base so let's create a constant in here where we say let's old array and we create an NS mutable array in here okay and then in here we say that the value is an array okay and then we say the array contains the values of Foo and bar like this okay then you can see in here that Swift playground says old array as Foo and bar right and you see oh this is let so we cannot change its internal values because if you for instance have a look at this one an array again okay which is created with let if you say more names and you say append and you say hello you will see that you will get an error in here it will tell you that you cannot append to this variable because it's created with a let statement or a let's syntax okay over in here since we're creating a let's old array that is equal to a class instance which is not a structure and again I completely understand that we haven't talked about classes and structures yet but just know that this is not and this is basic as its name indicates it is mutable internally it can be changed whether it is assigned to a let or a VAR it doesn't make any difference it is a class whereas this is a structure okay and structures are value types and classes are reference types okay so just know that for now that this is indeed mutable even if it is assigned to LED variable okay so now all of a sudden you can say old array and then you can say add and let's say baz all right and now you can see Swift playgrounds runs this code and tells you that indeed your let's constant what you thought was constant has changed internally all right now you can go ahead and create a new verbal and we say new array is old array and if you say new array add q u x in here Cox okay and then we say old array and we say new array now you can see the results in here since new array got the value of old array you add a new value to this new array and you'd expect probably for new array only to change not for old array to be affected however you can see the result that both old array and new array are actually referring to the exact same array so this can cause a lot of confusion for developers who are for instance new to Swift thinking that oh I just created a let immutable variable no one can change this however you can see that it got changed and even worse you can as if if you pass this value for instance to a function and that function itself can also change this variable so it is quite dangerous just by using let it's not that we're completely getting rid of mutability in Swift so a lot of things can go wrong especially if you're using reference reference types such as nsmutable array but don't worry about it I mean if if this is a little bit alien at the moment I will explain this a lot more in details later okay as I mentioned be very careful when you're working with mutable types in Swift and when you're passing them for instance to functions because those functions can actually change your mutable types even if they say they don't okay so let's have a look at this let's say we create another array in here let's let's copy this and I'm going to say let's some names and then we say Foo and bar okay so that's fine let's create a function and I completely understand we haven't talked about functions yet but this is this syntax of what functions look like in Swift so we say funk change the array and then we have an argument call array and in here we say NS array okay now I'll explain to you what nsra is nsra is the um and it's mutable array is the mutable variant of nsra and if you actually go to the source code for NS mutable array let's say in its Mutual array you can see that it's subclasses nsra so anywhere you have an NS Mutual array and sorry anywhere your function or call expect and NS array you can actually pass an instance of NS Mutual array to its because it will just work it will be downgraded to ns3 okay so let's say that we look at this function and this function just looks like it is working with an immutable array in here however internally it can say let's let's just say copy as array as in its mutable array so this is a syntax in Swift that you shouldn't really use that often but code can actually do that without without getting bugged by Swift really okay so you can see in here we're saying we're creating a copy uh oh a rage array like this where we're basically creating a variable that is called copy however it's not really copying the instance it's just named copy so maybe we could just call it array2 or something or just copy but uh just know that it is really not copying the value inside this or it is just assigning it to this variable and but it is setting its data type it's promoting its data type to immutable data type it's assuming that it is mutable okay it's this is really bad code you should never write stuff like this okay but I'm just demonstrating that it is possible to write code like this and you should kind of guard yourself against code like this and then in here we say copy dot add Mass okay now if you pass if you call this function change the array with your Mutual array everything will just work as expected some names and then you can say some names and have a look at the data now when this code is run you can see in this scope some names after being passed to change the array has actually been internally mutated you can see Foo bar and pass so this pass that this function added to this array is actually present outside that function as well simply because we're working again with reference types meaning that there's one copy of this in the memory and this function is actually changing the original copy okay so that was really uh it that's what I wanted to explain in this particular section of the video with variables and uh constants so just know that you have let and you have VAR and let it if working with value types such as structures of Swift arrays or strings or integers it prevents immutability of that value internally meaning that you can't change this van dot to for instance say and my name my name uh and then you can say is equal to actually my name make uppercase you can't do stuff like this so you cannot and like change the value that is assigned to this and you can't reassign a value to my name after it has been created okay so the reassigning that you cannot reassign a value to a let constant applies to both reference types and and value type so it doesn't matter if if the value inside this let constant is a string or it's an instance of a class as long as it's let you can't assign a new value to it for instance let's say here is you can see it is a sum names it is an instance of a class which is a reference type However the fact that you cannot reassign a value to this still holds true whether it is holding an instance of a class or an instance of a structure so let's say some names is blah in here now we should get an error in here saying that you cannot reassign another value to this after you have created it so this reassigning to a let constant applies both to reference types and value types however the internal mutability of a let's constant only applies the prevention of internal mutability of a let constant only applies to Value types such as structures if you've assigned a class to a let constant the class might internally change without Swift actually complaining at all okay so I completely understand is a little bit complicated and I personally believe that some other personal languages have implemented this a little bit more beautifully and a little more like fluid such as rust can I have some courses actually about rust as well so you can watch my Ross crash course for instance on YouTube and learn about mutability and rust as well but I I believe that Russ has implemented mutably a bit nicer than Swift and because Swift can cause some confusion in how it handles and mutable values but for now just know these simple rules and then we can move on to the next section of this video all right now that we've talked enough about variables let's move on to another concept which is very very important to learn in any programming language that you're learning at the moment and those are or that is operators so operators are small functions that are a little bit special in how they're declared and Swift treats them as such it treats them a little bit more special than other functions so and let's have a look at what operators are but before doing that let's create a simple playground for operators so let's say go let's say file new and we say file if we can find it oh we can't because we can't create a file inside this so let's be in here inside our editor and I'm going to say command n and then I'm going to go ahead and create a playground in here let's say blank playground and then we're going to say operators but be very careful because by default so if playgrounds or xcode actually tries to create this playground inside another playground and that is horrible it is really off full and just please just use the main folder to create your playground and also add it to the main xcode workspace structure as well in here so let's say create now we have operators and let's do the same thing in here I want to say import Foundation okay after doing this let's start talking about operators so let's create two constants in here let's say my age and we say 22 and we say let your age is 20 okay now let's work with our first two operators and those are the greater than and less than operators if you have two integers like this and I kind of expect you to already know what an integer is from other program language perhaps that you already know then we say if my age then once you have two integers you can use this particular operator that you can see it says greater than so the left side should be greater than the right side your age and your age and this is an if statement okay which I kind of already actually I kind of expect you to already know what if statements are so you can see now we're using an if statement and then and putting our left hand side and right hand side variables in here and using operator which is having this kind of a syntax so what this operator is doing is comparing the value to the left with the value to the right and it Returns the value of true if the value to the left is indeed greater than the value to the right okay and here then we can say I'm older than you okay and then we say else if my H is less than your H so this is another operator that works between integers for instance that says it will I will return true if the value to the left is less than the value to the right then in here we say I'm younger than you and else oh hey we are the same age okay so if I'm not older than you and I'm not younger than you then we should be the same age logically all right you can see nothing is happening in this playground because we don't have automatic running so I'm just gonna hold my trackpad on this button and then I'm gonna say automatically run and then you can see that our code is going to run in here and the value basically we got into this branch of our if statement I'm older than you simply because this operator indicated to Swift that the value to the left is indeed uh larger than the value to the right return the value of true and then Swift fell into this if statement so that's these two are the first operators that we're seeing in Swift basically however I mean there are some other very special operators such as the equal operator that we're seeing in here but we shouldn't really go ahead and explaining that we're simply assigning a value to a variable in here with that operator okay now there are other operators such as Plus for instance let's say let my mother's age is my age plus 30. so this is a an operator that is operating between two integers I can from the left hand side and a right hand side so it simply takes the value to the left and adds the value to the right to it and then returns that result to us okay so that's another operator that we're seeing in here the plus operator you can also of course use for instance the multiplication operator and we can say let's double and double my age is my H and you say times two and as you can see this is an operator that is sitting between two integers again it takes the integer to the left and and multiplies it by the integer to the right and Returns the value and which then gets assigned to this variable you can see it's 44. if you remember the age was set to 22 times 2 is 44. so you've probably now seen a few operators in here and you're wondering okay how many different types of operators are there and there are three different types of operators in Swift and I mean not I'm not counting these operators I'm just talking about three different types of operators okay the first one is called a unary prefix the second one is called a unary postfix and the third one is called a binary infix okay so when we're talking about unary as you remember let's actually write them down let's just say uh one is unary urinary prefix the second one is urinary postfix and then the third one is binary infix okay wherever you're seeing unary just know that this thing is working with only one value again working with one value and binary is working with two values okay so you can now imagine that this operator the multiplication operator that is working with two values is indeed a binary in fix it is binary because it's working with two values the left and the right hand side and it is an infix operator because it's sitting in between so infix in between okay it's sitting in between two other values so all the operators that we've seen so far the greater than or less than basically addition and multiple multiplication are binary infix operators we haven't seen a unary and Sr unary prefix and unitary postfix so let's have a look at unary prefix as you'd expect unary Works only with one value so let's say let's Foo is true so this is just assigning the value of true to Foo however if you want to change the value of this true to false and you want to flip it basically you use this operator in here which is the apostrophe operator which is a unary prefix operator that takes the value to its right hand side and basically um negates it okay so you can see in here true became false simply like that so this is a unary prefix it's prefix because it's before the value that comes right after it okay then we have a urinary post fix so a unary postfix offer is a little bit special I mean in all my years of working with swift I've been working with swift since summer of 2014. it is very very seldom that you create your own post-fix operator and you want to read postfix There are some unitary postfix operators already it's built into Swift but and you use them perhaps quite a lot however creating your own postfix uh unary postsex operator is something that you do very very seldom okay let's have a look at a unary postfix operator let's say name and I'm just going to create an optional value now I know we haven't talked about optionals but just for the purpose of demonstrating what a unary postfix operator is let's go ahead and write this syntax let's say optional and then we say rendered okay now if you want to grab the value that is inside this variable and unwrap it we say let unary postfix is equal to name and then we put this apostrophe after this name now just know for now that what the what we did in here is that we put an optional value into a variable call name an optional simply means that this name can either contain null values or it can contain a value that's what optionality in Swift means but I've prepared a completely separate playground for optionals which we're going to talk about a little bit later however this you can see now it goes ahead into this optional value and grabs the internal value and assigns it to this okay so let's say if we inherit say type of name and then we can type of unary postfix now they have two different types you can see the type of this variable is an optional string and the type of this variable is indeed a string so this unary postfix operator went inside this optional and grabbed its value out and forced it out and assign it to the variable to the left hand side basically using the assign assignments operator so this is a unary postfix operator it comes after a variable and it works only with one variable so it doesn't have a variable here and a variable there it is only working with the Val and the variable to its left hand side okay prefix unary prefix works with the value after it post or postfix works with the value before it okay so that's the second example basically for unary postfix now for the last type of operator which is the most common type and we call them binary infix simply because they work with two values hence the name binary and also infix simply because they sit in between the values that they work on okay so let's say a result is one plus two and this is a simple example of a binary infix operator you can see it's working with two values and sits in between them okay and other another example is let's say let names is equal to Foo and then we say plus empty space plus bar and this is another um infix binary operator that is sitting between two strings you can see you may be a little bit confusing you can say oh but if this is sitting between these two strings what is this sitting in between is it a prefix operator well it is not what is happening here is that Swift is executing this code from the left hand side because there is no parenthesis then it says okay Foo plus empty space becomes Foo plus like empty space like this and then takes this plus and uses it in between the result of the previous statement and Bar okay so that's what is happening inside this code basically okay so that was an example of a binary infix operator and as I mentioned most operators that you use in Swift are going to be binary and fix there are quite a lot of actually other operators as well but we don't use them so often okay depends again also on your code base now there is another category of operators and which is called a ternary operator okay and ternary is something that is a kind of a Hot Topic in any programming language that supports ternary simply because it can be misused and it can cause your code to look very very difficult to read actually so um what I suggest oops what I think is a good idea is always a check with your uh with your teammates who are working with your colleagues basically in your team and ask them if if they're comfortable with ternary and if they're if there are what are the um what are the boundaries that they that they feel comfortable using ternary operators within ternary can become very complicated especially if you're nesting them if you're using a ternary inside iternary and it's just good to check with people what they're comfortable with okay but let's just have a look at a ternary operator let's say let's a H is 30. now let's say that you want to display a message to the user saying that let's message and then you want to say if the age is over or equal to 18 then this message should say you are an adult however if the age is less than 18 then you should say you are not yet an adult how do you do this well what you could do is to say let's message is a string okay uh and then you could say if H is more than or equal to 18 then message is you are an adult otherwise message as you are not yet an adult so this works actually very well and you can type the message out you can see now it says you are not all simply because the H is 30 or if you were 16 it would say you are not an adult yet or you're not yet an adult however there's another way of writing the same exact code so let's just comment this out okay and that is using the ternary operator so in here you can see we've defined our variable first and then we're going using an if statement and an else statement and then assigning values to that variable okay however you can also say let's message is then you would put your condition in here you say condition okay and then the format is then you put a question mark then you say value if condition is met and then so let's put this to the next line and then a colon in here and value if the condition is not met so this is the format of a ternary operator first you put your condition in here so what is the condition so if the age is more than or equal to 18 so just let's just write it age should be more than or equal to 18. then we say that the value should be you are an adult then the value if the condition is not bad is you are not yet an adult and that is exactly how you write a ternary operator so you say you take your variable that you want to actually calculate the value of then you say it's equal to then you put the condition of your ternary operator and then a question mark after a question mark follows the value that you want to assign to your variable should the condition be met and then a colon and the value that you want to assign to the variable should the condition not have been met okay and you can see now the messages you are an adult and if you change this value again to 17 you can see the value will be changed to you're not yet an adult okay so I hope that you've now got an idea of some operators in Swift you've we've had a look at different types of operators in unary prefix unary postfix we have binary infix and we've also looked at a fourth category of operators which are ternary operators and again just be a little bit careful with ternary operators because not a lot of developers are actually very comfortable using these I met I personally like ternary especially like in these cases where is less code is understandable it's compact is not so much logic however some developers just write them all in one line like this and that can be a little bit difficult to read I I actually agree my uh habits in Swift is to manually break my code down into smaller bits and pieces like this into different lines as well unfortunately unlike some other programming languages like rust and dart and there is no internal analyzer as such sorry there are no formatter so Swift Code you need to format it by hand unfortunately and it has been eight years since Swift's come out and there is still no internal formatter for Swift of course you can select your code and then indent your code with Ctrl I in xcode but you cannot have xcode format of your code for you as you type so that is a little bit of an unfortunate problem that we have to deal with but it is what it is and we can just get used to it so if you want to make your code a little bit more readable I suggest that you format it a little bit by hand so kind of handcrafted as well okay that was really it for the operators so in the next section we're gonna look at if an else statement so see you there now that we're done with operators let's go ahead and create a new playground or if and else so right here I'm going to press command n on MacIntosh and let's say playground in here oops if I can spell it and a blank playground and let's just call it if else and please just ensure that you're not creating it inside an existing playground you can see in here it's called operators and we should change that to be inside our main folder basically okay and then we say it shouldn't be inside the operators group either it should be inside the group op ARP workspace so create now we can collapse the other ones and in here just like normal we say foundation not like normal actually like usual I meant to say so let's talk about if and else statements we've already seen a few examples of if and else and if you've already done programming in another programming language you should already be familiar with what if and else statements are so it's just a conditional basically okay let's add a few values in here so I'm just going to copy and paste some values and place them in here so some seed values that we can work with Okay let's create a simple if statement and then if sorry an if an else statement so we say if my name is equal equal valid so in here so like this and so this is using a lowercase v as you can see in here okay then we say your name is and then we're going to add our variable within a string and this is how you do it in so if you say back backslash and then parenthesis and then you say my name in here okay then in here we can say else and with no conditions in front of it and then we say oops I guessed I guessed it wrong like this and then let's do an automatic run for our playground and we should now come to the oops part because we guessed the name incorrectly with a lowercase v as you can see in here so this is a simple if statement so you compare something with uh with something else and then you can have an else block or not you can actually just have an if statement as well so you don't have to have an else Block in Swift okay now you're not limited in you're not limited only to one else statement you can't have else if as well okay so let's just say if my name my name is equal equal land up with the proper spelling as well with a capital V then we say now I guessed it correctly okay and then we say else if my name is Foo now you can see that we have another Branch so we have an if and then if that case is not met then the program will fall into this statement so it's very important to understand that it's not that Swift is executing both of these concurrently it's executing the first one first if that condition is met then Swift goes in here and ignores everything all the other statements inside the if statements so all the other else ifs and the last L statement if it is available so it's just branching basically okay so if my name is Foo as we say are you Foo and this doesn't really matter what you type in here I'm just trying to demonstrate how if and else if basically statements work in Swift and then we can have a final else statement in here and says okay I give up okay and you can see that Swift has gone into this Branch because name was correctly set to Van Dot and we're comparing it with vandan sorry it wasn't set to Vanda I mean it was set in here but we're actually comparing it correctly with the correct value in here okay and some people write their if statements a little bit more in like what I call a flipped way and here you can see we're saying if my name is equal to Vandal and so if you're reading it like you would read an English sentence I would say if my name is equal to valid however some people actually do it in the opposite way like this they would say if van dot is equal to mining so this is another way of writing it an uncommon way of doing this and a lot of old and like a little bit old school developers would do stuff like this it is not so common in all my years of working as a software engineer I've seen one or two people preferring this however me and my colleagues have been able to convince them otherwise that this is this we shouldn't do this in most modern Source codes don't do this however you may be an exception in so maybe you're working at a company where this is the prevalent way of doing if statements in that you actually put the value and that you and are testing um last and then you compare with the value and that you're expecting first as I said this is a little bit uncommon in my experience but maybe at the company that you are you and your teammates have decided that this is the way to do it it is completely equal to this it is the same thing as this code and I mean what it achieves is the same however the syntax is a little bit different okay so it is up to you and your teammates to decide what which way to do however if you're new to Swift I beg you to please don't do this and it is this way that you should learn how to write your if statements so please don't flip these values however if you're a seasoned developer and you know exactly what you're doing and you and your teammates have decided that in your code base all your if statements should be written like this or in just a few exception cases you write your code like this as long as you've checked with your team is and everything is fine then you go ahead and do it but if you're learning Swift just now this is the way to write an if statement okay and this is the way that almost everyone writes their if statements seasoned or not seasoned good so that was simple these are some simple if statements basically comparing a value with another value but what if you are having a little bit more complicated logic in here so let's say that you want to make sure that your name is found out and that your age is also 30. so you can see the age is defined in here as 20. let's just go ahead and compare it with 30 instead let's say if my name and in here if you want to compare also the age you can say and my age is 30 for instance okay then we say name is landlord and age is 30. then we say else if a my age is 20 then we say I only guess the age right and then an else statement in here we can say I don't know what I'm doing okay so as you'd expect now we're going to go into this line of code so what's happening here is that Swift started executing this code from left to right and I said okay from left the name is truly vandot and it started comparing the age and that says age is indeed 20 is not 30 so I'm not going to go into this if statement so it ignores this if then it looks at the code that follows this if statement and says oh it's an else otherwise if the age is 20 is the age 20 yes it is then it falls into this statement and then ignores the rest of the else so you need to think of if statements as in branches and they get executed separately not concurrently and they're basically in a Serial order from the first statement if it fails goes to the next statement then goes to the next statement if any of these statements succeed in trapping the logic so this one trapped and said okay if the age is 20 and in it is indeed then the code goes in here if any of these else statements or if statements do that the entire rest of this code is then ignored so this didn't fall into so this we didn't fall into this we did fall into this and then the rest is completely ignored regardless of how many else's you have in here you can say else if blah blah and then another else after that but all of those will be ignored okay now just like we have the an operator in here the logical and operator we also have the or operator okay but you need to be careful with it because you can actually make the code and do things that you didn't want it to do so let me just explain something in here so let's write an example let's say if my H is 20 not 200 or my name is Foo then we say either age is 20 name is Foo or both so what happening here is that you can see we say you may be reading this saying either the age is 20 or the name is Foo but what Swift does reading here says either the name at the age is 20 or the name is who or both of these so even if both of these are true then this code is executed and the reason behind that is that if your age is 20 then the code actually comes here just by default it doesn't even execute the rest okay so that is the reason that if age is 20 your name might indeed be Foo and that is what you've written in here but the code has already fallen into this simply because the first part of the condition was met so Swift doesn't even execute this part it says oh ages 20 of course let's go in here okay simply because Swift looks at the statement app versus oh said or so I don't have to execute it simply because I already know that my age is 20 so it falls here okay so it can be either this part this one or both animistics and developers make is they think that they can add another else Block in here and that else block will be executed as well and that is not the case because as I've explained it before if statements are zero and they get executed one at a time if any of them traps the um the execution of the program meaning that it actually results to the compiler understanding that oh this branch of code should be executed then the rest will be ignored so if in here you type else if my name is Van dot even if your condition is met which in this case is because my name is truly vandad or my age is 30 I started 20 which it was set up here if you remember my name and my age were van dot and20 respectively this code will not be executed so let's say it's too late to get in this class you can see that it won't be executed it won't be displayed in here only this branch is executed simply because my age was 20. okay and I can change it actually to Foo and you can see it still gets here first because my age is 20 and the operator after that is a logical or meaning that oh if this or this or both and it's since this one is true it doesn't even have to execute this okay so as I mentioned yeah or can actually or an and logical operators they can get quite complicated in that if you're if you're working with these operators and also parenthesis then you could create kind of confusing code as well and if you actually don't use parenthesis sometimes your logic could be completely incorrect let me just show you an example let's write a coding here and we say if my name is landlord and then we go to the next line and we say and my age is 22. okay then we go to the next line and your name is Foo and remember my name is my age is 20. your name is Foo at your age is 19. okay then here we're saying your name is who and we know that that is true in fact or your age is 19. okay so we say and what is this code actually doing so we say my name is Found Love and I'm 22 and your name is Foo Foo or you are 19. do you see what happening here so what happened was that and you can see that this message actually is printed here in our playground meaning that the code did fall into this as into this execution Branch so what happened you can say that my name is Vanda and my age is 22 but you can say well your age is not 22. how did this code come here and the reason is because we're mixing ands and ores and you can see what what Swift reads in here says okay if your name is Van Dot and your age is 22. and your name is Foo is this true then looks at all these ants this is yeah your name is but your age is not 22. then it looks at the rest that it could and says do I have any other logic to follow and it says yes actually you've written it here either these or that your age should be 19 and it looks at your age so uh Yes actually your age is 19. so you can see how this could be confusing for you reading this you may think oh your name should be vandot and your age should be 22 and your name should be Foo or your age should be 90 so you may think that this part is executed separately and this part is separate but since there's no parenthesis between these Swift reads it from left to right and then there's no uh precedence between the ands and ores so they have the same precedence so it says okay this entire thing is the same precedence and I just execute it from left to right and this or at the end basically traps the execution branch and ensures that the code falls into the if statement okay so writing code like this could be a little bit confusing what you might have wanted to write is this instead you probably wanted to say if and then parenthesis okay and then this is your own logic so you want to basically check your name and age so let's put it inside parenthesis so we say my name is founded and let's go to the next slide and my age should be 22 so you're basically saying and so you say my name is Vandal and my http 22. then you go to the next line and you say and and another parenthesis your name is Foo or your age is 19. like this okay so what is happening in here is uh and I can see our playground has some problem so what this really equates to I mean if you want to read it in English you could say my name is founded and I'm 22. and your name is Foo or you are 19. so do you see how this is differences your name and my name is Van Dot and I am 22 so this condition should be met and so should this because we are using an and meaning that not only this condition should be met but also this condition then it says okay well this condition is met because your name is Vandal and your age is 20 actually oops we have 20 here so that's that's interesting so so we wrote 22 that's fine I mean let's let it actually be like this so it says my name is Vandal and my age is 22 so it says oh this is not met okay so as soon as this is not met and this is an and statement it says oh I don't have to execute any of this now because I know that the left hand side of the and operator and The Logical operator is not exec is not true so I'm not even going to execute this okay then if we put an else Block in here then we can say hmm and let's say hmm that didn't work so well okay so if you put parenthesis between these and you can see that the logic becomes a little bit clean clear so and we can change this actually and we say let's say or okay and now all of a sudden you can see that this block of code is executed simply because either this should be true or this or both of them and since this part is not true it comes here it says your name is for indeed and your age is 19. do you remember H was 19 and name was Foo then it executes this code simply because one of these branches is true either this or this or both and we know that that this is true so it executes this code so usually you don't write code actually like this thankfully in Swift usually your code should make more sense inside your if statements and you shouldn't have too many branches like this with ands and ORS and parentheses but sometimes if you have very complicated code if you're working with low-level Logic for instance At Your Service layer you might write code like this so you should be ready to kind of be able to handle and read this type type of code but I completely understand it it is a little bit complicated to look at it if you're just looking at it like this and usually code like this is prefix with some common explaining why we're doing things the way we're doing them okay so that was it for our if and else playground in the next section we're gonna talk about functions so we can create a separate playground basically for functions after working with if and else statements we can go ahead now and work with functions we've seen a few examples of functions in Swift before and hopefully you already know what functions are so we don't have to go too much into details with functions but let's go ahead and explore some possibilities that we have with functions in Swift so command n in xcode or if you're in Visual Studio code I think also command n and or control n on Linux and we are going to just search for playground in here playground and let's say blank playground in here and let's call it functions and then let's create it inside the main group and inside the main folder okay and I think would be perhaps a little bit better if we change the size in here so I'm going to go to themes in Midnight which I'm using I'm going to select all of these and then let's just change the font size perhaps to let's just say 36 perhaps or even yeah 30 36 I think is good enough so we see the code a little bit better okay so with functions in Swift you have the same possibilities as you have in many other programming languages such as Python and dart and typescript JavaScript pretty much all the modern programming languages have some kind of same syntax and functionality for functions so let's have a look at a few examples so let's say we import Foundation I'm gonna get rid of that part to the left or Explorer so we can create functions in Swift with the func syntax or a keyword and then the name of the function and it should be camel case meaning that the first word of the function name should all be lowercase on all the subsequent words inside the function name should have or their first letter as uppercase and all the other letters as lowercase so here is an example of a function that takes no arguments and it has no return value so let's say no arguments and no return value you can see all the if the first word has all its letters as lowercase and all the other words have their first letters as uppercase that follow the first word okay then we put uh parenthesis in here and we can put our arguments in between the parenthesis but this function doesn't have any arguments then we do curly brackets and then inside the curly brackets is the body of your function and here we're just going to say I don't have I don't know what I'm doing okay and the way that we write these things in playground is a little bit special because in Swift playgrounds whatever you type as the string will actually be printed inside the playground's preview however this is not how you would actually write Swift Code so you would probably just issue a print statement okay but in playgrounds this does make sense so let's just do automatically run in here so our code gets executed automatically without us having to do anything and you can see nothing is being printed here simply because we're not calling or invoking our function now the process of invoking a function is just to tell to tell Swift that you want the code inside this function to be executed and the way to do that is just you use the function name no arguments and then with the parenthesis and any arguments that the function expects within the parenthesis now thankfully this function doesn't have any arguments so we don't have to pass any arguments within the parenthesis either and you can see the value is then printed to our playground console in here okay now we can also have functions that have arguments so let's create a function that takes any integer value and adds the value of 2 to it but this particular function is not going to have any return value again so we're just going to have a look at how to pass arguments to a function so let's say func plus two so like this and then we take a value and you can see this is how you specify an argument to a function in Swift you just type name of the argument and then you type the data type and also there's another way of doing this and I'll explain it later and you can have two labels for a variable one an external label and an internal label which is something quite unique to Swift you can have it in some other languages but not in all so here's an example of a function that internally creates a new variable let's call it new value and then takes that value and adds a 2 to it with a unary with a binary infix operator as we've seen before but you can see that it doesn't return anything okay and we can say plus two and then we can pass the value of 30 in here and you can see new value will be equal to 32 within this function all right so that's how you can basically pass a variable to a function using an argument you can have functions that return values as well so they do some calculation and then they return a value and the way to do that is to use this particular syntax as I'll show you now let's say new plus 2 and then we take a value of type integer and we return a value in here and then we can just say we return the value of value basically plus two and the return statements in these simple functions that just have one line of code is optional this is something that Swift has taken from rust however rust takes it to an entirely new level in that rust allows even for you to type some more code in here and then the last statement inside the function that doesn't have a semicolon will be returned however Swift doesn't have that ability so because semicolons are optional in Swift so if you don't want to have a return value in here if you don't want to type the return syntax in here or keyword you're more than welcome to do that the most modern code actually emits return so if you see a statement like this this function is set to return this statement implicitly all right and the way to call it is that you can say new plus two and then you pass the value of 30 and you can see the value of 32 will be returned from this function okay now you can also have functions with multiple arguments so let's say func custom ADD so we have a new add function in here okay and we take two variables so let's say value one int and value two int all right and then we return also an INT so what we return is value One Plus value two all right so we take two arguments value one namely and value two we add them and we just return them as part of our function declaration all right then we can assign the return value of this custom ad to a variable so let's say let custom ADD it is equal to execute the function of custom ad and for Value 1 we pass the value of 210 and for the second value we pass the value of 20 and you can see the result is value of 30. so this function is being executed and it's returned value is being assigned to this variable to the left hand side of the assignment operator okay now you can also have functions that do not have this outside label as as it is called so at the moment this function has two arguments and they only have one label this label is used externally as you can see at the call site and also internally inside the function however functions can also determine how these labels are created every argument can have two label sorry two labels external and internal okay so you can see that then internally inside this function this label is not available so if you type external there is nothing available but if you type internal then it is available to you okay so and let's go back in here and have a look at an example of a function that doesn't have any external labels all right so for its arguments so let's say func custom minus all right and it has two arguments and let's just call them left hand side and then right hand side and we return an integer as well okay oops and then we say left hand side minus right hand side now if you call this function just the way it is then you can you can write like this custom subtract it and then we say is equal to custom minus and then let's let's say let's say the value of 20 and the value of 10 in here okay and you can see then easily that at the call site we have to pass these argument names LHS and rhs however if you don't want to do that if you don't want to pass a an argument name you can just say custom minus and then you want to say 20 and 10 like that then you have to make sure that Swift gets the external name as underscore like this so underscore simply means that the a call site where you're calling this function from shouldn't have argument names so you can see now you have to remove LHS and rhs and then your code will work as expected okay so that's how you can basically ignore external argument names and just keep in mind that the first uh the first part of the argument's name can be its external name and then if you put a space and then another basically word or sentence hopefully not a sentence but a few words it will be the internal name of that argument okay and if you don't have that the only name you have in here will be available externally and internally all right good so um if you are now if you're in pure Swift you can see in here we're at the moment calling this a function like custom minus but if you're in pure Swift meaning that you're not inside a playground if you call a function that has a return value so let's say cost them add and then you say value one is 20 value 2 is 30. in a playground you just get the return value and the return value of this function will be displayed here however if you're in peer Swift meaning that you're not inside a playground then doing this will actually give you a warning telling you that you're calling a function without consuming its result the reason we're not seeing that morning in a playground is that playgrounds consume the result of all functions implicitly and and type them out here in the preview but inside pure Swift Code when you're writing like iOS code or Mac OS code or watch OS whatever and you're basically you don't have a playground in those codes it's pure Swift Code so you need to consume these values meaning that you have to assign them to something okay like that and then you need to also consume this somehow so even if you type code like this so it will complain saying that hey you're assigning this to add it but you're not using added anywhere so what's the point of doing this function call all right so if you want to write a function in Swift that does produce a value however the person or the call site where you're calling that function doesn't necessarily have to consume that value you can mark that function as discardable result and I'll show you how to do that so let's go ahead and create a my custom ADD function in here so we say my custom at okay and then we have two arguments in here that are externally not named but internally they're called LHS as in left hand side and then we have rhs in here okay and we return integer as well and we say LHS plus rhs so if you want this function to be able to produce integer but the call side the color of this function doesn't have to consume that integer you need to mark this function as discardable result doing this in a playground doesn't make any difference at all because as I mentioned playgrounds consume the result of all functions implicitly however if you're in pure Swift this will make a lot of sense and to be honest with you we can actually have a look at this I mean now I'm improvising a little bit I'm just going off the script but let me just create a simple iOS project in here and let's say my app and then we're just gonna save it on desktop it's fine I don't really care where it is saved at the moment so let's just save it and let me just show you how this looks inside a for instance Swift UI application so if you go into our app in here and say um what should we do in here let's say perhaps we have a window group in here let's go to content View and now we have a swift UI application though so it would have been better if we actually created a um let's just create a filing here Swift file let's say my service okay and in here let's just say that we have a what should we do let's say uh struct person okay and then we create a function in here just like we're learning now we say get H and this is not really how we write normal code anyways but this is for the purpose of demonstration and then we have another function that's called do something and then we say length age is get H so we call that function now if we leave this code like this let me just actually change this to yeah that's fine if you try to compile this code you can see that now we're getting initialization of immutable value age was not used or something was never used okay and you even if you write your code like this you will get a warning same result of call to get ages on you so this is the warning that I was just talking about inside a playground you don't get These Warnings but inside a pure Swift Code you get These Warnings so the way to fix that is to prefix this with discardable result and then compile your code you can see then it's working as expected however if you assign this to a variable you will get the warning anyways because you're assigning it to a variable that you're not using later so this discardable result doesn't fix this this issue however it fixes the issue of you calling this function without assigning its variable to any values sorry without assigning its value to any variables okay good you didn't have to create this project I mean this was just a test okay so that I can demonstrate what I meant in this case now that we have that we can just type my custom ad and then we can just say say the value of 20 and 30 in here without having to worry about consuming the result of this function now you you may be thinking but why would you write a function like that well some functions for instance in service layers inside an application may do some complicated work and they may produce a Boolean value indicating whether it was successful or not however it's not always that you actually care about that Boolean value and you can call that function without caring about its result in that case you can prefix the function declaration with a discardable result as I showed you right here okay now functions can also contain their own functions so this is something that not many program languages support darts for instance support so then you can also have something like that in Rust as well so let's have a look at that so we say funk do something complicated with a value and you can see width is the external argument label and value is the internal argument label in here okay and this function we can see returns an integer let's break this parameter down like this and then in here we say we have another function inside this that actually does the logic okay so we say main logic with a value and returns an INT and in here we just say Value Plus 2 okay so we're not really doing anything complicated we're just plusing the value with 2. however this function do something complicated contains another function that does the actual logic and this function then can call this function internally but no one else in the entire application can call this function this function is only available to this function because it is written inside it okay then what we can do is say return the main logic we call that function we say Value Plus three then in here we can go ahead and say do something complicated with the value of 30. so what happens is that the value of 30 goes in here then 30 will be plus 3 33 and then we'll go into main logic so 33 plus 2 will be 35 as you can see printed out here okay now arguments in Swift for functions can also have default values so you can have for instance a function that says Funk gets full name as you can see in here okay we say first name is the name of the argument internally and externally it has the default value of Foo and then we can say last name is a string and it has the oops the default value of bar okay and this function returns a string which is like this we put the first name in here and a space and last name all right so we're basically calculating a full name using this syntax now you can call this function now in so many different ways actually you can call in three different ways I would say one is without arguments so because both the arguments that are available that are required for this function have default values so you don't have to pass any arguments to it and you can also mix and match you can for instance pass actually I think you can call it in four different ways yes so you can also call it only with a first name if you want to so you can say bass you can say you can see now the result will be bazbar so the last name is picked from the default value and the first name is overwritten by the value at call site and you can also say get full name and then we say only pass the last name let's say Foo so now the value will be Fufu right and then you can also call it with both parameters so you can say first name and we say Babs and last name we can say like this all right so you can see now the result will be baz and Cox in here all right so these were just some examples of how you can create functions in Swift now we will actually look more at functions on how to create more complex functions perhaps but this is like the basic structure of how to create functions in Swift and there are some functions of course that are a lot more complicated than what we have in here but the complication is usually inside the function itself the function um header or the function signature is usually one form of these things that we've written in here with some param with some arguments that perhaps have internal or external names or some arguments that have no external names but internal names discardable result and pretty much pretty much that's it really so that's about functions for now in the next section of uh this video we're going to have a look at closures which are kind of special functions so see you there now that we've finished talking about functions let's go ahead and talk about a special kind of function which is with local variables and it is called closure so before we do that let's create its own playground so I'm going to go here and say command n and type playground in here if I can spell it and in blank playground I'm going to create closures in here and Ensure again that it is created in your workspace and not inside another playground I'm going to press the create button and let's say in here that import Foundation okay now closures are available in many other programming languages such as python there are also available available in Dart for instance and in I would say rust as well and of course JavaScript and typescript so most modern programming languages have closures and what closures really are there are special types of functions that are created in line so that you can actually pass them to another function for instance and they can hold a function so you could you could pretty much say that there are function references kind of but not really uh but I think the easiest way to explain closures is to demonstrate how they look like how to how the syntax looks like and I think after that it will be a lot more uh it it will be a lot easier to understand what basically they do so let's go ahead and create a closure in here which is supposed to add two integers together and return a result so if you were to do that using a function you would probably do add and then you would say like left hand side into your right hand side integer uh and you could perhaps also remove the external label of these arguments so that you don't have to actually write LHS rhs when you're calling this function then you would say that this function returns an integer then you could say left hand side plus right hand side is that function however if you want to assign this to a variable for instance call at then you could say let's actually comment this out then you could say let's add then as you would do with any other variable you as you could do actually with any other variable you don't have to do that but you need to tell Swift what type of data type this function is accepting so you could say let's add and then you would say column and instead of for instance saying this is an integer equal to one or this is a string equal to Foo you could say in here that this is actually a function right and then you say okay it accepts an integer and it actually accepts two integers and it returns an integer okay so this is you defining the data type of this variable or a closure okay and then you could say it's equal to so now you've defined a data type now you actually create the function then inside the creation of the function you just create curly brackets as you would do any other function and in here then you get your data you say left hand side is an integer right hand side is an integer okay and you return an integer and then you say in like this so let's actually break this down bring it to the next line like this okay so this is where you're defining the data type for ADD and this is where you're actually assigning it to a valid function all right and let's change our playground to automatically run in here and then you can see Swift is telling you that you're not returning anything in here so let's just say LHS plus rhs okay and these values that we have in here they're just internal uh argument names so they're not actually being used externally okay now that we have ADD you can see it tells you that add is actually invariable that points to F function which requires two arguments and returns also an integer so you could call at just like you would call the add function so if you say add 20 and 30 you can see that you're pretty much just calling that function that is beneath this add variable you could say okay so you get the result of 30. so now that you know how to create one of these functions closures you can see you can create it in line like that you can actually pass any one of these functions like these and which you create inline to another function and that's where the power of closures really come to play so let's create a quite a useless function and that we call custom ADD but it's just there for for the purpose of demonstration of closures so this custom function what it does it it takes two integer variables and then it uses another function that you give it so you pass a function to this function and that function is passed to this function will do the actual addition and R function that we will create now will just call that function all right so it will just demonstrate how you can pass a function to another function and how you can create a function on the go or on the fly so let's create this custom ADD function in here we call it custom ad like this okay and this custom ads it takes two uh two values we call them LHS left hand side all right and then we say rhs another integer and as the second parameter we want actually a function that does the addition for us so this custom ad itself doesn't really do the addition it will delegate the addition task to the given function so just like you would Define any other variable like here you basically type the external argument name internal argument name or just one argument name that is used externally and internally and then you would Define its data type this is very similar you see defining a data type with a column we did the same thing in here so we want basically a function that takes an integer or two integers and returns an integer so let's go ahead and Define it here we say the external label for this argument is using so we can say custom ad kind of like this custom at 10 20 using like this okay so the external name of this argument is using and internally is called function all right and then we say this function requires two integers and it returns an integer all right so this is just like defining any other variable inside or argument inside your function signature you just say external data sorry external argument name internal argument name it's data type and its data type is pretty much just a function with two integers as arguments and returns an integer okay after doing that we close the arguments list with the closing parenthesis and now we have to define the return value of R function so this custom ADD function at the moment you can see it's not returning anything because the parenthesis ends here but we don't have any of these pointers in here so let's say that our function also returns an integer okay then inside the function itself inside this custom math function we need to return an integer but it is this function that does the calculation so let's just call it just like you would call any other function so we just say function LHS and rhs and again this is just a label it doesn't have to be called function you can just call it f if you want to or you can just call it l h whatever you want to but I really really suggest that you don't name your variables with f or H or L it's just better just to call them something and that means something as well okay and in this case function I think is a quite a good name for it but you might disagree so we have function now and you can see it is being called by custom add-ins and this result is being returned from Custom app and you can call the custom ad function as I'll show you now so let's say custom ad you can see we have three parameters okay I'll break them down here now the left hand side you can see it doesn't have any external labels so let's just say 20. and then we say 30. now this using is going to be very interesting because usually when you come here Swift is going to be able to substitute this for you using an a trailing closure syntax okay so if I go here and press enter you can see all of a sudden the using label was just completely removed now if if you go ahead in here and you just want to see okay but what is happening in here what you could do is instead go ahead and create a function in here because this should be a function you see it's telling you it needs to have two arguments and a return value of integer you could create a function yourself and then say left hand side and right hand side ends and it should return an INT and then in here you and also please don't forget the in syntax because it needs to know Swift needs to know where this function actually starts its body okay then in here you say left hand side plus right hand side so after doing this you can see now the value of 50 being printed to the playground console all right so that's what you could do manually however what syntax what Swift does is that if it sees an argument at the end of a function you can see sorry an argument at the end of the list of arguments of a function so here we have a left hand side and right hand side and then we have a closure that has to be passed to this function but disclosure is not like the first argument it is the last argument and Swift does something called a trailing closure syntax what it does is that and we can actually do it by hand we can go in here you can see it removes this argument name first of all then it puts an ending parenthesis here and then removes this column then you can see this should pretty much do the same thing in here so and then it of course removes this parenthesis in here as well so now you can see the parenthesis ends here and then there's no using since using argument name and then there is a trailing closure right after the function is finished so we can actually put this maybe here actually it's good yeah and we can clean this up as well a little bit like this so this is the trailing closure syntax in Swift meaning that if there is a closure at the end of a function and then it shouldn't it doesn't necessarily have to have all the bells and whistles around uh argument names and Etc okay it can just emit writing the argument name close the parenthesis right after the argument before it and then creates the closure right after this function call and it will be passed into this argument okay so now you saw that we created a closure which is this one and we passed it to another function which is then being used to calculate the value of 20 plus 30 okay now Swift also has a very handy functionality where it can infer data types based on the function signature now I'll explain this a little bit now and you can see in here this function custom ad already has defined that the closure being passed to the function argument has to have the data type of integer integer and it sorry it has to have the data type of integer for both of its arguments and also integer first return value now in here then you could say okay but if this function already knows that it should be integer and integer maybe I could just remove these well it kind of would be right you can just go in here and say left hand side right hand side and then in and if it runs your code again you should basically see 50 again you can see in here so we could maybe change this to 30 just to see that everything's working as expected uh there we go we got the value of 60. so you can remove these data types right so if let's actually copy this code and bring it a little bit down here and remove the data types like this and we can remove the return value as well so that's the first step of cleaning up the code that you can do all right now a lot of developers would call this actually clean up they would say oh yeah you should remove these data types they're not so good Etc however I've worked on a lot of big projects that have been written in purely in Swift and once your code base gets very very large that you have maybe thousands of source files and then every of those source files has hundreds of lines of code on average perhaps written in them I've noticed that I mean after doing a lot of uh benchmarking on the compilation and asking xcode to tell me exactly where things are taking a time or the most time during the compilation it's been where it has where the compiler has been trying to figure out data types so there's a little less information you give to the compiler the more time it takes for the compiler to compile your code so here you can see we have a lot of information for the compiler we're telling it that this closure has two arguments integers and it's returning an integer so the compiler doesn't have to figure it out on its own so it says okay then I just calculate this and return the data however here the compiler has to ensure that yeah okay so the function it has to go back to the custom ad function and say okay this shouldn't have two integer arguments and it should return an ins then it comes here and checks that because we haven't even told it what return value we have then it says okay there's some data here some data in here and they have to be plus together can two integers be plus together okay so it's it has to figure figure out all of this on its own so it has to basically look up the plus function or in fixed binary operator to ensure that that actually exists between two integers so you can imagine all of this basically puts strain on the compiler and of course if you have thousands and thousands of these functions that where the compiler has to figure out things on its own then of course your compilation is going to be drastically slower now now that we're talking about stripping information from the compiler there's also one more step that you can take in order to make your code more Compact and more difficult for the compiler to guess but on small smaller code basis this is this doesn't really make any difference to be honest so let's actually copy and paste this code right here what you can do in this case is that you can completely remove these this information from here and in Swift you can tell it that you have two arguments in here by specifying by prefixing every argument with its index and dollar so you can say dollar zero plus dollar one so Dollar in here will mean basically an argument at an index of zero which is this guy and an argument at the index of one which is this guy and then you're just plusing them together and returning the value so some developers will then be like custom at 20 30 and then we'll do like this so it is completely up to you and your teammates how you like to format your Swift Code because unfortunately there's no real official linter and official code formatter for Swift as I mentioned before so there are some Community guidelines how to format code but you can't actually see code written like this sometimes and to be honest with you for me at least this is readable I have nothing against it but if it was me writing this code I would probably write it a lot more like this just because of the experience I've had with ensuring that the compiler can compile my code faster on larger code basis but writing code like this is also completely fine dependent on the context all right good now now that we've done that let's have a look at passing um some sort of special closures to functions and before I before we do that let me just write some coding here as uh like a preparations let's just Define an array in here and say and I'm also aware that we haven't worked with arrays yet but if you've worked with another programming language you already probably know what arrays are so it's just like a homogeneous uh actually they can be heterogeneous as well but it's just like a series of data okay let's just leave it at that let's just say ages are 30 20 19 and 40. so now we have four integers placed inside this array okay now you can see in here we can start sorting this array let's say that we want to sort things ascending and descending so we say sorted okay and you can see it has an argument in here and there's a function called sorted using actually let's just say sorted by let's say sorted by this a little bit better and you can see it expects a function so it says give me a function that takes two integers and then it can throw and we haven't talked about throws it and it should return a Boolean okay so let's go ahead and see how we can implement this function so we say LHS integer rhs integer and it should return a Boolean okay and then actually it throws as well but we don't have to write that and then we say in all right so in here let's just return true for now and let's see what happens okay so if you return true in here let's see the data that is being returning here uh ss14 19 20 30. so it really didn't do anything so but if we say in here uh LHS should be more than rhs okay and this is of course it's going to return a Boolean value all right now you can see what happened is that the result is that the return from age is that sorted is an array that is sorted descending so as long as left hand side is more on right hand side if you're basically doing this comparison with greater than then you're sorting the array descending and you can read the documentation if we're sorted by as well to understand how it actually works okay so it's when you want to sort a sequence of elements that don't conform to the blah blah let's see and that returns true when the first element should be ordered before the second so it says return true when the first element should be ordered before the second and and what we're saying is that if left hand side is more than the right hand side then it should be sorted before and that's why we're getting descending and if you change this to less than you should expect your rate to be sorted ascending okay so what what I'm trying to doing here is that we have a lot of code in here you can see that takes left hand side and right hand side returns a Boolean however there as you may guess this particular um operator which is a binary infix operator already takes a left hand side and a right hand side and returns a Boolean so if we were to Def to implement this uh operator ourselves we would probably write it like this right function less than and we say left hand side integer right hand side integer and it returns a Boolean and we say left hand side less than right hand side however please don't do this because this actually goes into a something called an infinite Loop it will go into an infinite recursion of itself because this function will just call itself all right so what I'm trying to say in here is that if you look at this function signature you can see it is exactly the same as this function signature so and since this is a function name in itself why don't we just pass it to this so instead of writing all of this why don't we just do this right because it is the same thing it is the exact substitute of this so let's remove that and remove this code as well and you can see actually you can do that so by passing a function or an operator a binary in fix operator to this to this argument you're substituting pretty much all this code that we wrote in here so a lot of newcomers to Swift will write code like this but a lot of seasoned developers know that that and this binary and fix operator already is a substitute for that closure so you can do the same thing for more than so this is going to sort descending and this is going to sort ascending so you can see here descending sort and ascending sword okay so that was uh one one example or rather two examples of passing operators to closures okay now let's move on to the next example and for that I'm gonna go here to our custom ad function and I'm gonna copy it right right here and let's paste it down here and let's call it custom ad2 and if you remember I mentioned that we have this syntax called basically trailing closures in Swift meaning that if there is a closure at the end of the function signature as its list of arguments then Swift helps you out by removing by allowing you to remove the and the argument label and allowing it to Trail basically the closure at the end of the function call as we saw in here so you don't have to type and using in here okay which is something that we otherwise would have to do all right like this using this and then parenthesis so since that function as since this argument is at the end then we don't have to do all of that work however if you make a mistake of putting this argument for instance at the first place where are in the middle not at the end then let's see actually what happened in here with a comma then calling this function you will have to do something like you have to do mental gymnastics like this custom uh two and now you have to pass your closure like this all right and then you say LHS and rhs and then you say LHS plus rhs and then you have to go in here and say 20 and 30 for instance okay so I don't know about you but this code looks a lot dirtier to me than it should be because it has a lot of labels and it is like it is a function or a closure before these values being sent here and so to me this doesn't look very clean to be honest with you and you can of course make this a little bit shorter as well you can remove that code that you've written in here and you can say dollar zero dollar zero plus dollar one and then do it like this and then go 20 30. so it becomes a little bit more readable if you do this however it's still not as clean as it can be so you can also put perhaps the value of 10 in here just to demonstrate that this is actually working as expected so now this should be 60 okay so um that's why I really suggest that you take advantage of trailing closure syntax in Swift and add your closures if you have a closure argument at the absolute end of your argument list okay now we've seen how we can pass uh operators like this to a closure parameter of a function and but as you as you'd expect since arguments sorry since operators are normal functions and you can also pass normal functions to closures so let's have a look at an example let's create a function in here it's called add 10 2 and then we get a value of integer and we return an integer and we just add 10 to this value all right and then we can have another function in here called at 22 and then we just add 20 to whatever integer parameter that is passed to our function now we can then have an a function in here called do addition all right and then it takes a value and we externally call it on and we say do addition on value all right int and then we want to have a function that basically takes this value and does some addition with it and returns an integer okay so we say using a function using function and this function should take an integer as its only argument and it should return an integer okay so that's so it shouldn't take two integers basically simply because we want to pass one of these functions which has only one integer as its input to this closure in here okay and our function should return an integer than what it's going to internally do is going to invoke that function with this value and return its result as the result of our function we could have written return in here but it is not necessary in modern Swift okay now let's go ahead and invoke this let's say do addition and then we say on the value of 20 and in here using you could you could imagine that well you could create a trail enclosure in here you can see and we say value and we could say value plus 30 okay so what is going to happen in here is this value of 20 is going to be passed here to this closure and it's going to be 20 plus 30. so let's see if Swift playground is going to be able to recover and you can see 20 plus 30 is 50. now instead of doing this instead of passing this uh into basically an inline closure to this using argument you can as you'd guess pass a reference to any of these functions that has the same and they both these functions have the same um header or definition as this closure they take an integer as their argument and they return an integer so let's say that we say add 10 to like this and you can see now it's this function internally going to be passed through this so this function is going to be at 10 2 and it's going to be invoked with the value of 20. 20 plus 10 is going to be 30 which is which is then printed right to our playground console then let's copy this and go here and then we say add do addition again on 20 but add 22 which is our other function up here okay and then we have the value of 40 printed to the screen now and this function is a little bit strange as you can see I mean not strange actually they don't have external argument names so if you change that and so that the value is actually the external argument name then you have to change the signature past here as well so then we should say add 10 to with value and add 22 with value so just make sure that your function signatures are basically the right signature according to how you've defined those functions in here okay very good I think this suffices for uh closures really closures are as I've mentioned uh kind of inline arguments and usually that you pass to another function and you can Define closures and by assigning a function to a variable and then you can pass that variable around to other functions as well so really when as Swift developers talking about closures they're just talking about functions that are in line so they don't have the funk keyword before them so any function that doesn't have the fun keyword behind it is in fact a closure instead you could pretty much just say that okay good we're done now with closures and we can now move on to talking about a little bit more fun stuff in Swift um namely structures see you there so we're now done with closures or at least for now let's go ahead and start talking about structures I think from this point on in the course we're gonna actually have a little bit more fun since we've talked about the absolute basics of Swift up to this point and you can imagine that the basics are not so fun and I think for me at least personally personally the fun part comes in when we have enumeration structures uh classes protocols extensions generics all that so let's get started with that I'm going to go in here and let's do command n and xcode and let's create a blank playground and we're going to call it structures okay structures again a warning please click create this not inside another playground just change both the group and the folder to the root of your or to your workspace basically okay and then we say create so we have structures and let's import Foundation as usual I'm going to get rid of the Explorer to the left hand side so structures in Swift are a way of grouping data together and giving some sort of a name structures in Swift are value types and meaning that when you assign an instance of a structure to another variable then the data inside that structure gets copied over so you don't actually get um it get you don't get the same reference using two variables I know it I mean this could be a little bit difficult to understand for especially those who are not familiar with value types from another programming language but don't worry about it I'll explain it all soon so let's just first of all go ahead and create our first structure which we're going to call person okay struct person and in here when you create a structure you can then go and instantiate it so you can create an instance of this person such as let Foo is person okay and you can see then you do this syntax in here with parenthesis and inside this parenthesis you would eventually pass any arguments that the Constructor of this structure requires at the moment the structure doesn't have any values inside it so it doesn't contain any properties so that's important to understand the term property it doesn't have any property and we could go ahead and create properties and the way to do that is using the let's or VAR RM scene keywords in here so you could say we have a constant in here called nape and its data type should be string and all of a sudden you see your playground is going to give you an error in here if you have automatic running as well especially it tells you that you are missing an argument called name let's just ask it to fix it for us and we say name okay it's a string and we say Foo in here okay just like having the name property in here you can create another property for instance called H and we could say it is an integer now you see playground will give you another area in here saying that you're missing the age argument and we can ask it to fix it and says H okay then we say 20 in here okay now you can see we've created an instance of person with two properties name and H all right now you can access these properties using something called a DOT notation so if you go in here and say Foo dot name and food.h just like that and Swift playground is going to be able to print and consume the results of these and print them to the console as you can see in here however if you're writing pure Swift Code this will make no sense you're basically saying food's name but you're not doing anything with it but since Swift playground implicitly consumes the result of all variables and all return data it is being printed in here but in Swift it is more likely that you would say let's name and and age is foo's name and then plus food that's age inside like a string or something okay so I'm not going to write all of that but you you get my point so you have to consume it in another way if you're not using Swift playgrounds but just know that you can drill down inside a structure using this notation which is called a dots notation you just put the name of the variable that points to structure and you say dot and then you get the properties out okay now you can also have custom Constructors for your structures as you can see in here we didn't actually have a Constructor and the Constructor for structures is always created by the compiler itself and this is one of the reasons a lot of people prefer to use structure as a swift rather than classes simply because you don't have to create Constructors for them Constructors are implicitly created by the compiler so if you add another property in here there will be a new Constructor so which will replace the old one that had only name and age with the new arguments in it as well or the new property in it as well okay so that's one of the properties of Swift structures that they have implicit Constructors you don't have to create yourself now if you do want to create a custom initializer or Constructor for your structures you can also do that I'm going to show you how so let's create a structure in here and we say Commodore computer okay for those of you who are old schoolers and have worked with comforters one of my favorite computers it was actually my first personal personal computer at Commodore 64. okay and so we create a common computer and we say let's name okay and your name is the name is supposed to be something that you designate it could be like my lovely Commodore or whatever and then we have another property in here called menu Factory I always have difficulty writing and spelling it and we say it's the string now in this case if someone wanted to go ahead and create an instance of commodore computer it would probably go let's say Commodore 64 is equal to color computer and they would say name and then they would say my commodore and the manufacturer is always always going to be a Commodore okay so in Commodore 64 has the manufacturer of cover and also Commodore 128 is going to have a my color 128 okay so both of these instances have the manufacturer as Commodore then you can ask yourself okay if you have a Commodore computer who always has its manufacturer equal to Commodore why should the call site meaning this part pass this value over and over again so you could create a Constructor that always sets this value for you to Commodore let's go ahead and have a look at how you could do that so let's go ahead and say we have an initializer you can see in here okay so you just type in it not funk in it except you just type in it and it implicitly becomes a function then since it is a function then you have your argument list and then your function body then as you as you can expect in here you just want the call side to pass the name to you so you're just say name String but you emits the manufacturer from the initialization so you say self name is name all right and you need to prefix this name which itself simply because if you say name is equal to name it just thinks you see it highlights the name it says name is name it's the same thing you're not actually referring to the name inside the structure so you have to say self that name so Swift understands you're referring to this name being assigned the value of this argument okay and then you say self dot manufacturer is Commodore so you yourself take it upon yourself to assign a value to this property okay then you can go ahead and say let's 6 c64 is Commodore computer and you can see the only argument that the call site has to pass to you is the name so you say c64 then you can say c64 name and c64 at dot manufacturer and the values will be exactly as you'd expect them so it'll be c64 and the manufacturer will be Commodore as you've set it inside the initializer or the Constructor of this structure okay now there are other ways of actually doing that so what you could have done in here instead of having a custom initializer in here or a Constructor you could have commented this out and he said in manufacturer equal to Commodore like this okay so this would have achieved the exact same result so you don't you don't have to have a custom initializer if you want to assign values to your properties that don't change pretty much okay so just keep that in mind please so there's another way of doing that okay now we've looked at that let's have a look at another type of properties that you can create inside your structure and those are called computed properties and I'm going to show you the Syntax for them now for that let's go ahead and create a new structure so we say struct and we call it person two unfortunately we've already consumed person in here so we can't have another structure called person unless we go ahead and comment this out but we're not going to do that let's just create a person too but please if you're working with production level applications please don't do this please don't call your structures or classes two or three or four unless your business logic requires you to do that okay which in all my years of software development I've never had the requirement of calling something two or three so um just keep that in mind please this is just for the purpose of demonstration in this playground okay so let's go ahead and create a person person structure in here with a first name and last name so I'm just going to say first name is a straight and then I'm going to copy this and go ahead and change at first to last so we have first name and last name now let's say that your requirement in here to create a property for your person 2 structure called full name so this full name should always be equal to the first name and the last name with a space in between it so what you could do is to go ahead and create an initializer for your person too and you could say full name and you can see in here you can't just say full name is equal to first name and last name because you will get actually an error in here and you this this syntax is invalid so let's actually have a look at here cannot use instance member last name within property initializer because at the point of you assigning this value to full name first name and last name are not known so even though this might make sense just looking at it but Swift compiler doesn't work that way so you could be tempted to go ahead and say okay I will create an inch socializer in here and I say first name is a string last name is a string but I don't want you to pass me to full name I can't figure it out on my own so you say cell first name is first name self last name is last name and cell full name is a string consisting of Ace another string which is the first name which is passed in here as a parameter and then we will have a space and then last name so this actually is completely valid Swift Code there's nothing wrong with it I would say however there is a better way of doing that and that is used and that is called computer properties so what you could do is to completely remove this initializer in here and then change this let's to a VAR and then make it a function so this is a computer property when you have a variable and inside and then for the variable value you actually have a function in here okay and in here you could just say first name and space last name so now you actually did what we wanted to do from the beginning when we said equal to you see we try to do this but that didn't work all you have to do really all you have to so this is what we try to do at first but in order to get this to work you have to say first VAR Define the data type to remove the equal sign make it a function and then put the logic in here and that will be valid Swift Code okay so you can now go ahead and create an instance of this structure let's say a let Foo bar is person two we say pers first name is Foo and last name is bar like that then we say Foo bar first name and foodbar last name and then we can have access to a property called full name just like you have access to first name and last name you can see first name is Foo last names bar add full name property or computer property is set to food space bar okay and this is how computer properties work all right now structures the way they're created is that they don't inherently allow mutation right so let's let's have a look at an example every I mean everything we've created so far has been immutable meaning that we haven't been able to change the structure internally we've just instantiated those structures and assigned some values to them and after assigning value to them we couldn't actually change those values so we can't go in here and say c64 name as well so this is going to give you an error because this is not assign it all right you can see we got an error in here okay so how do we make sure that we can create structures that are mutable so you can actually change them after you create an instance of them so let me show you an example of creating a function that can mutate a structure okay so let's create a car in here car structure and then we say current speed is in an integer let's just say current speed then we can pass 10 or 20 meaning 10 kilometers an hour for instance now what if you want to have a function in here a funk drive with a specific speed okay and then in here we could say driving but what we want to do is to change the current speed of this car with the speed that is given inside the drive function so if you say current speed current speed is speed you can see now you immediately get an error in here saying that you cannot do that so it says cannot assign to property current speed and because it is a let constant so you might say okay let's fix that let's change it to VAR then this will not work either because you can see now you get another error saying cannot assign to property self is immutable so the suggestion that and that's uh xcode playgrounds is giving you it says Mark the method as mutating so let's fix that and you can see the suggestion actually works so this function is prefix with the keyword of mutating allowing the car instance to be changed and the reason behind all of this mental gymnastics is that structures inherently are immutable meaning and and they're also date and there are also value types meaning that once you've created an instance of it it's sitting in the stack and it shouldn't be changed but if you create a mutating instance then then a mutating function you're basically bending the rules of how structures are actually working and it's completely valid Swift syntax as well so it's nothing illegal but I think actually in I mean all my years of working with swift it is not so often you want to do something like this and but there are a lot of classes inside Swift itself that have mutating functions but usually when it comes to structures you don't want to mutate them but sometimes you have valid reason to do that okay so let's go ahead and create an immutable car you may be thinking okay but what does that mean but this is a mutating function I'm going to show you what I mean let's create an instance or a variable car called immutable car and we're going to say it's an instance of car and this current speed is 10. then you can go ahead and say immutable car and then you could say drive and with the speed of 20. all right you can see now you're going to get an errand here saying that oops you're calling a mutating member on an immutable value or variable and it says immutable car is a lead constant so what happened here is that since immutable car is let you can't you can't actually call a function that changes the internal value of that let constant and this is one of the very subtle differences between let's and VAR in Swift if you remember when we talked about variables at the absolute beginning of this course I mentioned that there are some small differences between let's and bar which we can't explain right now and this is one of those differences what Swift is doing in here saying that okay you create a let constant in here and you're saying that it is equal to an instance of a structure but then you're going ahead and trying to change it by calling a mutating function on it if this function wasn't mutating and we didn't have this code in here you would be able to easily call it you can see no problem but if this function is marked as mutating you're telling Swift that this function is internally going to change the data inside the structure and since this is a let constant it is not allowed to change either so by changing I mean you're not either allowed to do this so you can't do this and you can't change it internally either so both of these are invalid okay so that's what let's stands for in this case so how do we do that let's just comment this out and go ahead and create now a mutable instance of car how do we do that well of course there's a syntax word and the svar it's a variable it can change so we say mutable car is a car with a current speed of 10. then you can go ahead and say that car Mutual car like this and drive with the speed of 30. and then you see mutable car current speed then you can see the current speed is Gonna Change to 30 in here okay so um what we're going to do then is to have a look at a little bit of copying values and seeing how that also affects our mutual mutability so let's just remove this code for now and if we go ahead and create a let copy of this so we say let's just say copy is immutable car so what what we're doing in here is we're taking the value inside mutable car which is an instance of car and we're assigning it to a new let constant called copy since structures just remember that structures in Swift are value types meaning that if you assign an instance of any structure to another variable the internal data of that structure will be copied over to this variable meaning that now you have duplicate cars one is in the mutable car and another one is in copy and they have absolutely no connection to each other let's demonstrate that and we say mutable car in here and we say drive it at the speed of 30. and then we say Mutual car and current speed and then we say copy current speed now you probably think oh they should both be 30 but you can see that the mutable car which was actually mutated using the drive function it has the current speed of 30 however the copy has the current speed of 10 at the point it was it was taken or basically it took over a copy of mutable car at this point mutable car had the current speed of 10 as you can expect from The Constructor or initializer okay so remember structures are value types when you assign a value of a a let constant for instance or a variable and where it is equal to an instance of instruction to another variable then you're basically getting a copy of that structure and you might be thinking okay is that is that because of let okay let's test that let's change this to VAR and see what happens in here you can see it didn't really change anything by assigning simply assigning an instance of a structure to another variable whether it's VAR or let you're making a copy of this and placing it in here okay so that's a very very important thing to understand about structures so structures in Swift cannot subclass other structures okay and subclassing is something that comes into play when we talk about classes but I'm naming it in here we haven't talked about it yet but I'm naming it here because as I mentioned at the introduction to this course I expect you to already know another program language and chances are you probably know JavaScript or python or Dart for instance or rust and you are probably comfortable with subclassing though rust doesn't really have subclasses it it has the concept kind of like protocols okay but I just want to mention that Swift structures cannot have the functionality of subclassing and I'm gonna I'm gonna explain that how subclassing pretty much works but we're going to go more into details about subclassing when we get to the definition of classes in Swift and that is going to come up soon okay for now let's create a oops a struct and we're going to call it living think and in the init function we're just going to say I'm a living thing all right now you may be thinking okay a living thing could be an animal for instance so we create a structure and we say animal and you would expect it to be able to subclass living thing like this you would say an animal is indeed a living thing but you can't do this this is not a valid uh Swift syntax you can see this is inheritance from non-protocol type living thing so just keep in mind structures cannot inherit from each other in Swift okay so let's comment this code out and we just leave it there leaving thing is still evaluative syntax so we could just leave it there okay now in Swift you can also have custom copying of structures and as we saw when you assign a value inside a variable to like here we had mutable car and you sign it to a copy let constant the entire contents of this mutable car was copied over to this variable but what if you want to have some sort of a custom logic while copying over something to a variable well you have to create that logic yourself let me show you how let's say struct bike we say manufacturer okay and we say string and we say let current speed is integer all right now if you say in here let's bike one is a bike and we have a manufacturer of Harley Davidson in here and we say let's say the current speed is 20. so not nothing illegal and then we're going to create a bike two in here so we say let's bike two and then you say uh bike one now what you want to do in here you say well I want to get bike one but I want to change its as sorry but I want to change its speed when it is being assigned to this variable you can't do that at the moment right because even if you change this to VAR and if you say Bike 2 current speed is 30 you can't do that simply because current speed inside the bike is specified as let you can't change it you then go say okay I have to change it to VAR then well you'd be right you can't change it to VAR and everything will just work fine but remember you have to do all of this work simply because you had this requirement in here to assign a bike to another bike and change its current speed there is another way of doing this and it's actually more preferred I would say to do it this way that I'm going to show you is to create a function that allows you to do that so you could go ahead in here and and say well I have a function and I'm just going to call it copy it doesn't have to be called copied you can say copied with or whatever you want okay then you can say copy and then you say current speed so you want to change the current speed so take it in as an argument and then your function could actually return an instance of bike itself then you say okay I create a bike its manufacturer is the sales manufacturer because remember this is an instance method meaning that it is actually operating on an instance of bike itself so it has access to self and the manufacturer and its current speed is going to be the current speed that is coming from the argument itself in here okay so now that you have that you can go ahead at call site in here and say bike one copy with the current speed of let's say 30. and then if you change this back to lats you can see it works as well and by two current speed is now uh 30 and we could also say bike one current speed and you can see that should be 20. so this is one way of creating copies or custom copies of your structures and to be honest with you there's not much more to structures I mean it you have to just get the concept of mutability and structures and also having the ability to have arguments and sorry having the ability to have properties in here we talked about VAR properties as well that can mutate and we also talked about computed properties which can return a value by assigning a function pretty much to and that's argument sorry to that property of the structure so there's not so much more into structures and I think we've talked enough about them in the next section we're going to go ahead and talk about enumerations so let's create the enumerations at Playground now so command n playground and blank playground and let's call it enumerations and in here I'm going to say it is created inside the main workspace let's change the group as well to the main workspace in here and press the create button okay gonna get rid of the Explorer and let's say import Foundation all right now let's talk then about enumerations and immersions are one of my favorite features of Swift and any other program language that supports it and I think actually almost all languages that I've worked with except for assembly of course support enumerations or a form of enumerations I mean Objective C does it C does it have C plus plus does it typescript does it JavaScript is it python does it Dart rust all these languages I've worked with have the concept of enumerations and that's that's very good I mean and they do have enumeration spot to a certain degree they differ from each other so some have more advanced enumerations such as Swift I would say Swift enumerations are the most advanced I've seen and after that rust enumerations are number Advanced and then we have also JavaScript and typescript which are at the same level kind of like Dart animations but also Dart is less advanced in supporting different features of enumerations what are animations I mean I've talked quite a bit now about enumerations but what are they well enumerations are categorization of similar values that are named such as animals cats dogs and rabbits you could put them inside an enumeration now if I for instance ask you and I said let's create a structure in here struct animal and I said define the type of animal in here you would probably say Okay type is a string and I would say okay so can I create an animal and its type is a bike then you say okay so what should we do should we go ahead and create an initializer in here that takes the type and it says if type is a rabbit or type is Doc or type is cat then self-type is type otherwise you create a preconditioned failure of oops it didn't work something like that so this is valence syntax and uh it is going to work but it is not so obvious I mean a lot of cases it probably people don't even see your source code so they have to kind of guess what type they have to pass in here and that is the reason we have enumerations Innovations is the categorization of similar data together by a name so let's have a look at how that actually works let's say an enum animals okay and we can remove the structure from here and this enumeration let's also have our playground as automatically running and it's animals in here then you can Define your different types of animals giving them names and the way to do that is by using a case syntax in here or a case keyword then you say you can't I have a cat I have a dog and I have a rabbit now when I say I have I don't actually mean that these are properties I mean these are cases this animal's enumeration has these various cases and you can also omit case for every one of these cases and remove it and just do it like this as well this is also completely valid Swift syntax so you don't have to prefix every case with the case keyword but a lot of people do that and it allows you to also go to the next line I mean you can also do this but it looks a little bit strange to be honest with you if you do something like this I haven't seen animations in Swift in all my years like I've written like this it's either written like this or it is written like this usually okay but it kind of depends on you and your team how you want to Define your animations I think what would be really good if you and your team decided on a convention of how you want your animations to be created either all of them have case before them or you just have one case for all the cases basically okay so you may be thinking then okay now that we have this how do we create an instance of these animals so we could say let cat is animals dot cat as you can see in here you have all these properties in here cat dog rabbit Etc let's say cat and then we can print it out here to the playground console and you can see it just says cat you can change this to dark and you can see it says dog in here though we have to change the variable name probably as well okay so that's the simplest way of creating an instance of enumeration now you can compare enumerations with if statements so if we go in here and we say if cat is equal to animals cat then this is a cat and we can say else if cat is animals animals dot dog this is a dog otherwise this is something else okay and of course you can continue here you can say else if cat is animals dot uh rabbits however in here you can't say else if cat is equal to three and this just won't work because 3 is an integer and cat is an instance of animals so you cannot compare you can see it says there's no comparison operator between animals and integer and you would be thinking then oh maybe I should go and create one and you could do that you could say funk equality and so this is an in binary infix operator on the left hand side you have an animal animals and on the right hand side you have an integer and you return a Boolean and you could say if you could say you return left hand side left hand side is equal to cat and right hand side equal to three okay so then this returns a Boolean and now you can see your error will go away so you could do something crazy like that in Swift but please don't do it I mean I'm just showing you different ways of doing things but this I just want to tell you that this is not okay to compare an instance of a an enum with an integer for instance okay however there's another way of doing this using its raw value but we haven't talked about that yet so let's just remove this and remove this entire if statement from here like that okay so we just have an else and you can see as you expect this statement is being executed simply because cat is in fact an instance of animals dot cat all right or an instance of animals rather equal to cat okay now if statements are a little bit strange in that you would have to write quite a lot of code if and then else if and then you have to compare them with animals etc etc there's another way of doing this and that is using a switch statement I'm going to show you how to do that if you say switch on an instance of an enumeration then in here you can get help actually from xcode to complete it for you you can see and you just press the fix button and it will tell you that okay I know that cat is an instance of animals and I know animals has cat and dog and rabbit I will type it out all for you so you can see that syntax is case and then the enum value and then you can type some code in here and you can say break meaning that as soon as it hits that point you just break out of this switch statement like this okay so let's go ahead in here and say this is a cat and this is a dog and this is a rabbit all right so we've written our code and we expect this line to be executed and if you go ahead in here and change the value of cat to a dog then this case is going to be executed you'll see soon this is a DOT right so let's change it back to cat again so this is how you would do a switch statement and then there's a Syntax for switch statements where you don't have to specify all the cases so if you don't want to specify the case of rabbit you can also do that just remove it but you're going to get an error now as you'll see soon it'll say that you haven't covered all the valid cases it says it must be exhaustive meaning that you have to cover all the cases but if you don't want to cover all the cases there is a special syntax called default in here and say this is something else which is similar to our else statement right so these two are pretty much the same our One is using a switch the other one is using a um an if and else statement now oh I probably I should tell you that this is usually not a good idea specifying a default clause simply because in the future I mean uh let's let me actually demonstrate to you let's go ahead and in here say that you have a funk and you want to say describe animal and then you say animal is of type animals okay then you go in here and you say describe animal and let's change the switch to uh from a cat to an animal in here which is passed to us then we say describe animal and we pass our cats to it okay um in the case of cat we're saying this is a cat in the case of dog we're saying that this is a dog and in here actually we don't have to pass Cat to it we can say animals dot rabbits okay if we do that you can see it says this is something else now what if we go ahead and add another case in here and we say case Hedgehog I think it's spelled like this now you can see our function is still saying this is something else so for every case of our um animals where it is not handled it's neither cat or a dog it's saying this is something else well this might work in this example but usually in larger applications when you add a an enum case to your animations you want everywhere where you have a switch statement to actually take care of that case okay so let me show you how if we remove this case from here so we have cat dog and rabbit again we go in here and we bring the case of at rabbit okay and we say this uh this is a rabbit and we break okay and we can actually take this out we don't have to have it inside a function anymore we take it out all right and then say in here we say switch cats so we have all the cases covered now cat dog and rabbit now if another programmer inside our team goes ahead and adds a case of Hedgehog you can see our if statement still works and you might be thinking well the if statement still works it must be good but the switch doesn't work so it's not good however in my opinion where you go ahead and add a new case on enumeration you need to also always ensure that everywhere you're handling an instance of that enumeration you're taking care of the new case as well the if statement doesn't do that it doesn't fail because it's simply doing comparison however switch is doing more than that it's ensuring that if you're switching on an enumeration that the enumeration cases must be exhaustive meaning that you have to cover all the cases so in in my opinion with my experience it is always almost always best to compare enumerations using switch okay because it will tell you that oh you can't upon your code now because someone has gone and added a new case through the switch you have to handle that so let's handle Hedgehog in here and we say this is a hedgehog okay and we break so now you can see it is handled and though this is still a cat so this statement is being called but at least we've handled the case of adding a hedgehog in here okay now now that we've taken care of that let's talk about enumerations a little bit more advanced enumeration Concepts and that is enumerations with Associated values okay animations in Swift have the ability to have Associated values a dart for instance for those of you who are flutter developers you probably think that Dart also has that but unfortunately it doesn't and in Dart enumerations you create an enum and you can't make it a class almost by adding properties to it and then you create enum cases that hard code the values of those properties and that's not really the same thing as having enumerations with Associated values like Swift and rust half because as you'll see soon enumerations in Swift can have Associated values that are dynamically added at the time of creating the an instance of that narration okay let's for instance have a look at an integration called shortcuts or shortcuts let's say in here you want to create three shortcuts and one is called for instance a case File or folder okay another one is a www URL and then a shortcut to a song so let's say that you're creating an enumeration that can allow the user to do a shortcut to any one of these cases either a song for instance on Spotify or a website address or a file or folder now how do you go ahead and do that how do you then say okay this let's say let www.apple is shortcut to www URL but how do we specify that this is actually going to go to Apple all right then you you would probably think that okay I want to add case www.apple.com or something like that well if you had to do that then you would have to create a case for every website in the world and that won't work and that is the reason we have Associated values for enumerations is Swift and rust so let's go ahead in here and you say I want to add some values to these guys whoever is creating an instance of any of these cases has to pass some values to them then we say for instance here the path is a URL you see in here okay so then at the call side we're creating an instance of this WWE URL you have to pass it a URL okay so we say let's go to the path and we create a URL and in here we say it's a string of https and apple.com and we force on rapid we haven't talked about this operator yet actually I think we talked about it once is um this is a unary suffix operator which we've actually seen an example of before okay when we're talking about optionals but you see we haven't gone into depth and with options yet so just accept that this is a URL for now okay but we don't have to know exactly what this one does I'm going to explain it soon when we go and talk about options all right so you can see now we actually passed a value to an instance of this uh enum case and you can do the same thing for others like file or folder we could say it has a path to a URL and it has a name of string okay and we could say a song has an artist a of type string and a song name of type string all right so this is up to you I mean it's really up to your imagination What values you want to have associated with your enum cases okay now you would be thinking okay now that we have this guy how do we compare it with like if if there is a case in your application where you get a copy of an enumeration or an instance of this enumeration if you want to see whether this is a song or a URL or a file or folder how do you do it so you would probably say of if ww apple is equal to shortcut dot dot URL and then let's say you pass this URL to it boom then do this okay so you may be thinking okay I could do that but no you can't really do that you can't do comparison between an enum instance with associative value and another in immenses with the same associative value because as soon as you add Associated values to enumerations in Swift you basically you need to Define equality for this enumeration yourself there is no equality by default anymore in this case when we had animals and there was no associative values we could do this because Swift adds implicit equality operator which is a binary infix operator to enumerations with no Associated values by default but as soon as your animations have Associated value Swift doesn't know how to compare them anymore because it's not the comparison of their cases anymore but you actually have to define a comparison yourself maybe you want to only compare the names in the case of file or folder maybe you don't care about the path maybe in the case of a song you don't care about the artist you just want to basically compare the song names so Swift can't deduce that equality operator for you so you can't do that unless you go ahead and you go ahead and and basically Define equality operator which is a little bit more advanced than what we're going to go into right now so as you'd guess you can rely on your friend switch statement so we say switch dot Apple in here and we can actually ask Swift to complete this for us you'll see now it'll be a little hint in here it says fix and you can see it will come up with all the cases for us okay now I usually don't like the default format that is created in here but we can use it for now I'm just going to break them down into smaller parts in here into smaller bits of pieces of code now in here we could say print the path print the name and then break okay in here as well we're going to say print the path and then break and then here we're going to say take the artist to its own line sign name to its own line and then print the artist and then print the song name and then break like that all right so now we can see that we're going to hit this point and it says that you are the path of this URL is actually apple.com all right and actually I think in here yeah it was called path as well but here it doesn't have to be called the same just so you know this path it doesn't have to be so you could say let P okay the important part is this one now there is another way uh you can also remove the argument names so you can see in here it says there's an argument name path and then it's a let path let's copy this and make it cleaner let's copy this entire thing so this is what Swift suggests that you do but usually in codes in code bases or at least the ones I've worked with no one does this okay no one says here's the artist and then let's artist no one does that what usually people do is go ahead and chain and remove this external argument naming here and just leave the let's in here okay so remove the path and remove the previous thing in here as well and this and you will see that this works exactly the same as the other one all right so uh that's another way of writing it and what is also very very common in Swift uh code bases is that people don't like the syntax of writing let's before every argument name either so you could copy this code now let's clean it up even more gonna paste it here and remove all these let's okay so that let this let as well and also these lengths from here and what we're going to do is to go ahead right after the case type let right after the case type let right after the case type lets so this let is going to be applied to all of these arguments in here and you can see it works exactly the same way as it did in the other two examples every example is going to become shorter and more compact than the one before it basically okay really good now there's another very compact way of unpacking values inside in iterations that have Associated values now there was two values in my sentence but I think you get the point and that is using an if statement in very rare cases if you want to only handle a specific enum case uh for instance in this case you want to see if this dot dot apple is an actual URL you could use a if Case let statement you could say if Case let and to be honest with you in all my years of doing Swift I still get this wrong almost every time I sometimes type if let case and sometimes if case something something and then let but the actual syntax is if Case let all right and then you say the case is dot dot URL which is your actual enum case and then you say pass is equal to your variable then you can print out the past so you can see it's printed in here so you can in here then say it could be anything else it could be file or folder and then you could say path and then name all right equal to your enum case like this and you can see it is not executed simply because.apple is not an instance of file or folder enum case in here let's change it back then to drop.url and then we can grab the path out of this variable instance or a shortcut instance in here okay now while you're working with enums you can also ignore values inside the enum cases let me show you how let's say we create a an instance of shortcut we say without you is an instance of shortcut to a song by one of my favorite artists Symphony X and the song name is called without you so one of the really good songs of Symphony X I highly recommend that you watch it and sorry and listen to it if you want to I don't actually think there is a music video to it unfortunately uh but there may be one of these lyrics uh music videos to it on YouTube so now we have without you and we want to compare it if it's a song by um for instance only looking at its song name so we say if uh case let and it is it a song and we don't want actually we don't care about its artists so we can ignore the artist using an underscore in here but we only care about the song name and we say if that is equal to without you in here then we can grab the song name okay so you can see it's it says without you without actually using the artist in here you could also say artist and then type the artist in here as well and grab that artist you can say it's a Symphony X but if you want to ignore the artist you can just pass underscore in here okay really good now you can also have a case statements and switching case for enums with Associated values that have similar data types okay let me let me actually show you an example of it let's go ahead and create an enum of a vehicle all right and we say one is a car and every car has a manufacturer of type string and a model of type string and then we have bikes as well and with manufacturer as well and like this but for bikes we don't want a model we want a year made integer okay so this is an enumeration now you may be thinking okay let's say that you have this business case of uh every time you access an instance of vehicle you may want to grab its manufacturer so how do you do that let's let's go ahead and say let car is vehicle and how do we do that let's say vehicle.car for its manufacturer we say it's a Tesla and for model we say it's model X then we say let's bike is a vehicle bike okay and its manufacturers Harley Davidson and it's your mate let's say 1987 or something like that okay just making things up in here okay now how do you grab the manufacturer out of these two like you have a car and you have a bike and you want to grab their manufacturers you know both of them have a manufacturer but how do you grab that well you could go ahead and say okay I switched the car I'll let Swift extract this information for me for all the cases then add this in here then you say okay I have the manufacturer I will learn that we can have a let statement in here and remove all of this in here so we have the manufacturer we don't care about the model so underscoring here then you say manufacturer manufacturer and then you break and you do the same thing for bike okay you say case let manufacturer is right there and the year made we ignore and then in here you say manufacturer and break okay so this is a switch on the car all right and you can see we grabbed the Tesla manufacturer out of that car but what do we do with the bike oh yeah we have to go ahead and do the same thing for bike we go ahead in here and we say switch on the bike and we say in this case since it's a bike you see Harley Davidson is extracted then you may be smart and say okay I'm sorry and not you may be smart you are smart but you might try to be smart to say okay then I can create a function out of this then I will say funk um get manufacturer from vehicle okay and vehicle of type vehicle and it returns a string and in here you could just say return manufacturer and return manufacturer you could do that as well okay so this is actually one step closer to making this a little bit more usable and then you could call gets manufacturer uh from car and then gets manufacturer from bike as well okay so you could do that as well so you get Tesla and then oops what happened to our bike the manufacturer should be Harley Davidson so car manufacturer bike manufacturer oh because we're switching on car this is very very bad we should switch on the vehicle in here okay which is a local variable to the function then we get our Tesla and we should now soon get Harley Davidson so this is this is another step towards having a more reusable extraction of manufacturer from our vehicles what you could do is to move this actually out and place it inside the enum itself and instead of switching on a vehicle that is passed as a function we can remove this and say we switch ourself all right and then we go in here and then we can say car gets manufacturer okay and then we could say bike gets manufacturer right so that's one one more step actually towards having it a little bit more Compact and having it make more sense so it's a car get manufacture and buy get manufacturing now both of them have the same function however what you could do is to have this as a computed property enums just like structures can have computed properties so let's say VAR and we change it to manufacturer and we say it returns a string and now all of a sudden you don't have to call this as a function you can actually say manufacture just like a property right like this good now it's one step closer to having it very clean there's one more thing that we can do to have it even better and that you can see that these both cases case let car case like bike they're pretty much doing the same comparison they're extracting a manufacturer and ignoring the second value well what if we could just remove this and remove this case and have a comma here instead so we say in both cases the case of car and byte we're returning the manufacturer and you can see that this is valid Swift code and it is doing the exact same thing right so if you have pattern matching in your enumerations like this where two enum cases or more are having the same pattern matching by grabbing one value and it doesn't necessarily have to be this to be honest with you it could it could for instance be in the case of bike and sorry in here model and you can ignore this one and instead use the model in here so actually you then have to call them the same thing let's say Foo Foo and then you return Foo okay so pattern matching Works basically just by matching the value types since both of these are strings and the other stuff is being ignored then you can use this food but we actually broke the code because instead of the car manufacturer we're returning the car model in here but I just wanted to demonstrate to it doesn't necessarily have to be at the same place so it doesn't necessarily have to be like the same at first value of both cases okay so this is a computer property on an enumeration and it is returning and it's doing a pattern matching on the both cases and it doesn't have separate case statements in here okay really good that part's also done now apart from enumerations with Associated values you can also have enumeration with raw values and here's an example of that so let's go ahead and say enum family member and then in here you can actually say that we have a case of Father case mother case brother and we have a case sister but what if you want these cases to for father for instance to be called Dad so to have that value of that so you want to for instance have a mother be equal to Mom then you can say Okay father is that mother is Mom brother is bro and sister is sis okay but we're gonna get an error now simply because it says that this integration can't have values like raw values like this what you need to do is to tell so if that this enumeration has raw values of a specific data type like this so you could say it is a string basically all right and now Swift is very happy so what you could do then is to say family member dot father and then you have a new property in here called raw value then you can grab that Dad value out of Father case and it is a string you could do the same thing with brother or mother and sister as well okay so brother is going to say bro in here okay um now you can also have a enumerations in Swift that have that you can extract other cases because if you go into family member at the moment you can see that you have brother blah blah in it raw value but you don't have you you don't have the possibility of extracting all the cases inside this iteration but you can do that in Swift by conforming to a protocol called case I turbo we haven't talked about protocols yet we're going to do that soon but for now just it's enough if you understand the syntax so let's say enough favorite emoji and we say it is a string and also we're conforming to a protocol called case I trouble okay just learn it for now that if you do this Swift allows you to go through all the enum cases using a property as you'll soon see so let's say case blush is equal to blush in here okay and we say case rocket is rockets in here we then say case fire is fire like this all right then you can go ahead and say favorites emoji and like that and we say we have a new property here all of a sudden call all cases all right you can see it says blush rocket and fire so it gives you all those cases okay and also you can grab their values you can say favorite emoji not all cases now we're going to use a function called map and we're going to get their raw value and please don't worry if this doesn't make sense I'm just demonstrating what you can do but we're gonna talk about these things when we talk about collections later all cases is now an array of your favorite emojis okay so if you make an enumeration conform to this case I triple protocol I think it is actually a protocol yes then you can you can grab all the cases out of your uh out of your enumeration using all cases property okay now now you have enumerations you can also I mean you can create instances of them using like uh favorite emoji.blosh favorite emoji.rocket but if you have an if you have the value of an enumeration how can you create an instance of it so using so right now we have been able to say favorite emoji.blosh dot raw value so we get the value but if you have the value can you reverse it into blush so if you have an emoji like this can you actually grab an instance a favorite emoji using the Emoji itself and yes of course you can do that and the Syntax for it is if let blush is favorite emoji and you can say using a raw value of your emoji in here then you say found the blush emoji and then you can print it out to the console otherwise this Emoji doesn't exist like this else if I can spell it right now you can see it says found the blush emoji and then it actually prints it out which is blush it's not the Emoji itself you see it is actually the blush case of the Emoji the favorite emojis enumeration favorite emoji you can see in here okay but don't worry too much about this because we're going to talk more about these in later chapters when we talk about optionals at the moment we haven't talked about optionals so this might look a little bit strange to be thinking what is a flat well it is strange because we haven't talked about them yet but this is just an example all right let's copy this as well and do another example then we say let's see and create instead of blush in here we're going to say snow and we say snow exists really so let's Pass snow in here and see what happens because we haven't defined snow as one of the cases in here you see we don't have a snow Emoji so and then we say try to create an instance a favorite emoji with this note and if it is created then type this snow exists really okay and then we can in here say as expected snow doesn't exist in our em so we expect actually to get in here because snow doesn't exist as one of the cases of our enumeration okay now we've looked at these and don't worry about these two particular examples because they're using optionals and we'll talk about options more in the future okay now let's talk about mutating members of enumerations now just like in structures you can have mutating functions inside enumerations and the way to do that is by prefixing the function with mutating as you did with structures so let's say enum height and then we say we have cases of short medium and long and then we have a mutating funk in here Funk make long all right and by mutating an enumeration you're pretty much just assigning a new value to self because there's not much more you can mute it with an enumeration than actually mutating it itself so in here then you can say self is equal to height dot long all right so you can basically assign it back to your own self and change yourself instance using a mutating function on an enumeration okay so let's go ahead and say we have a variable my height is equal to height medium and then we say my height make long and then we say my height let's see what it is so once it is executed first is medium and then we made the heights equal to long in here as you can see okay and if this was a let constant then you wouldn't be able to do this you will see now that make long can't be executed simply because it is trying to mutate self all right good now we're done with that now and there is another Concept in Swift iterations which is a little bit more advanced but I wanted to just name it and they're called recursive enumerations or indirect iterations and in all my years of working in Swift I think I've used them once once or twice it is very uncommon that you see indirect enumerations and that's why I've left them as the last concept to explain it here but I think it's still a good idea uh to explain them so let me show you what indirect or recursive enumerations are in short a recursive Innovation as its name indicates is an enumeration that refers to itself so in here you can see we had Integrations that just have short medium long and even have we had iterations in here with Associated values that we're not referring to themselves you can see in here they just had associate values of URL but no Associated values of touch shortcut again okay but let's go ahead and create a new enumeration in here which has reference to itself we say enum int operation and then we say we have a an addition let's say so we're ex we're basically defining an addition between two integers okay so it's just a case it's not a function we say k subtract and then we subtraction subtractions between two integers as well and then we can have a free hand this is a special uh case that we're creating which refers to ins operation itself all right so what's happening in here now you see we'll again an error saying that you cannot have error you cannot refer to yourself unless you mark this enumeration as an indirect enum as you can see in here okay so you can now see that issue has disappeared but what does this actually really mean and what it means is that now you can have a free hand operation on this ins operation and I I completely understand this is a little bit complicated and we don't have to learn this but let's just let's just see how we can create a function now on this enumeration that calculates the results based on the cases let's say we have funk calculates results and we say that the parameter is off operation and we say ins operation in here okay as optional and we say that's equal to nil and again I completely understand we haven't talked about these yet either and in here we could then basically calculate the operations and by doing a switch statement I'm just I'm just going to paste that in here so we don't have to type all of this to be honest with you okay so let's see what happening here we have the operation or self an unexpected non-void return value and in here we should return an integer as well okay so what's happening is that we're we're basically switching on this operation since it's optional we're saying either the operation or self itself and we're saying if it's an addition then do addition if it's a subtraction do subtraction if it's free hand let's actually change this to freehand with a capital H if I can spell if it's freehand then call this function recursively with that operation and the result to this really is that you can go ahead now and say let freehand is into operation dot freehand okay and in here then you can say do an addition of two and four and then you can say freehand uh and you can say freehand dot calculate results and then you can see the result being printed in here of six again please don't worry this is very complicated this is almost going to like Advanced Swift and as I said in all my years of working with um Swift I've had to use I think once or twice uh indirect iterations and if you didn't learn this it's completely fine it was kind of expected to answer it and that's one of the reasons I'm kind of jumping over it and pasting code because I don't think there's so much value in spending time learning about indirect or recursive enumerations so just know that they exist but you don't have to learn it okay so let's close off the iterations chapter with this indirect iteration and that is probably a better idea actually if you just remove this whole thing from here so you don't have to be taunted by the thought of having indirect iterations so uh at least for me it doesn't feel so good to end the chapter with something that we just jumped over but I just want to explain that this exists so you know about it okay good now we're done with enumerations in the next section of this video we're gonna talk about classes now that we've talked enough about enumerations let's go ahead and talk about the next concept which we've actually named before and you probably know them from other programming languages that you're already familiar with and that concept is classes so let's create a separate um blank playground for this so let's say playground in here and we say blank playground and let's call it classes and just again ensure that you're creating it inside your main folder or workspace and then we say in here create and like we usually do we just say we need to import foundation in this playground and again hold and the trackpad in here and say automatically run okay so we have structures in Swift and we also have enumerations but there's a third category of storage space you could say in memory and that is called a class and and classes are like structures but they're not value types they're reference types and also they allow for mutability without having to prefix things for instance with mutating a syntax or keyword so let's have a look at a simple class in here so I'm just going to say class person and let's say VAR name String and then bar age ends okay and so this is a simple class now it has two variables and let's see oh we're getting an error in here and simply because we have no initializers and this is actually really good we're getting this error um because um I actually didn't think of explaining this first but now that it has appeared let's talk about it as you saw before if you have a structure like let's say in here we say class person sorry struct person and let's actually put exactly the same code inside the structure and comment the class out and you can see everything will just go fine with the structure you don't need an initializer or a Constructor for a structure by default an implicit one will be created for you with all the member variables added to the argument list of the Constructor so if you say person you can see name and age are already there however when it comes to classes you always have to create Constructors yourself there is a refactoring feature in xcode where you can ask xcode to create the Constructor for you I'm not sure if it is available inside um playgrounds and we can see that it isn't maybe there is a menu somewhere let's let's say Constructor or initializer generate member-wise initializer and that's the one but it doesn't seem to really work in playgrounds so we need to just use this little hint in here and ask it to perhaps oops yes it is not really allowing us to actually add an initializer it's trying to add a default value to these properties and that's not what we want to do so a class's first difference to a structure is that it needs to have a Constructor or an initializer and we already know the Syntax for it and that is within it and then in in the parenthesis you would add your arguments in here okay so let's say we have a name which is a string and then H which is an INT and again the um not again actually we haven't talked about this before but the ordering of these arguments it doesn't necessarily have to be the ordering of your properties so it can be anything in here and you can actually ask for more stuff let's just say height and I don't know what you want to do with that because you're we don't have a place at the moment to store it but you can ask for more things than your class actually has as properties because maybe some of those values are going to be using other ways inside the Constructor of your class okay so let's take this back to having name and agent here all right and then inside a Constructor your job is to first and foremost ensure that your class as properties are all set before the Constructor is finished so you cannot return from a Constructor or an initializer as Swift calls it and without having initialized or all your stored properties okay so it says name needs to be stored I need name needs to basically have a value and then we're going to go ahead and say self that's name self that name is equal to name right and then we also have to say self-h is equal to H alright so that's that's the simple initializer but we haven't really looked at mutability let's have a function in here and say increase H all right and then in here we say self age is and we're using this operator in here which basically takes the left hand side and adds the right hand side to it all right so now we have a function in here you can see it's increasing the age property by one and it doesn't have to be prefix with mutating actually I think if you type mutating in here it will give you a syntax error is not valid on instance methods and classes so you shouldn't actually prefix anything in your in your classes with mutating all right then you can go ahead and create an instance of this class let's say let's Foo is a person with the name of Foo and the age of 20. all right then I'm going to break these into their own lines then we're going to say Foo H have a look at the age and then we say Foo increase age and then full H all right so let's have a look at these values then you can see first the age of Foo is 20 and then after think after incrementing it using the increase age then we get the H equal to 20. so nowhere in here did you actually have to create anything mutating and you can see that the variable itself is actually created with a let so that's the second difference when you create a let constant equal to an instance of a class you cannot assign a new value to the select constants constant because there is one of the natures of a left constant after creation it cannot be assigned a new value so you cannot go ahead and say Foo is equal to some other person in here so that rule stays the same when it comes to let constants and classes however since now you're working with the let constant equal to an instance of a class this class internally can change as you can see the age has changed without you having to change this to afar so that's the second difference between classes and structures in that classes allow for internal mutability without you having to create an actual VAR out of them all right and also their reference types and we'll talk about that soon actually okay so let's and let's have a look at what reference types actually mean so in here we say Foo age let's bring this down Foo H maybe just type it again in here and then we say bar is equal to food all right and then we say bar increase H now you'd probably expect bar to be copied and have actually a new copy of Foo however since classes are reference types the reference of this Foo is placed inside this bar so pretty much after line 30. bar and food point to the same instance of person in memory so bar gets a reference to this Foo and then by increasing the age of bar then Foos age is also increased and bars H is exactly the same so they're basically pointing to the same memory and memory space or memory allocated memory for this person's person instance okay so keep that in mind it's very very important now you can also compare instances of classes by using the equal equal so the triple equal syntax which in all my years are working with so if I've never had to use so it is very unlikely that you'll have to use it however if you want to see if two instances of a variable pointing to a class are pointed at the at the exact same memory space then you would use this syntax you would say if Foo oops if I can spell is equal equal bar okay and I think I've placed actually my fingers on the right on the wrong place on the keyboard so that's why I'm typing everything incorrectly so let's say Foo and Bar point to the same memory otherwise we say Foo they don't point to the same memory and then you can expect that you get this printed to the console simply because yes the r actually pointing to the same memory space and if any if for for those of you who are curious you'd be probably thinking okay what happens if I just change it to this and we should ideally get an error as you can see in here and that is simply because we haven't implemented equality on this class so person doesn't conform to equality in here and we'll talk more about equality perhaps a little bit later but if you wanna basically ensure your class instances are Equitable then you have to say Equitable in here and then you go ahead and Define a static Funk equal like this but we will probably talk about this a little bit later just know that this equal equal is not the same as equal equal this basically tests if two variables hold values that internally are equal to each other base based on some logic however this is some logic that Swift has implemented and you don't implement this in this logic at all what this one does is just make sure two variables are pointing to the same memory allocation all right and as I as I mentioned before you probably don't use this so often now classes unlike structures can also have inheritance meaning that you can create a super class with some logic and then you can have some other subclasses that conform to that actually not confirmed but they subclass that's super class all right let's have an exam have a look at an example in here so we say class vehicle alright so we have a simple class and we say go vroom like this and in here we save room vroom like this alright doesn't necessarily have to be anything scientific then we create a car class which should subclass vehicle okay so we say it's subclasses that vehicle in here and the car doesn't have any implementation of its own then you can create an instance of car like this and then you can say cargo vroom so you can see car though it doesn't have an internal implementation of Gover it it has inherited that function from its superclass namely vehicle in this case so keep that in mind you can have inheritance using classes which is something that you cannot do in structures okay now classes can also have private Setters so you can actually have a variable and that is marked as VAR but can only be set privately so you can see in here these variables are just simple vars meaning that they can be both internally changed and also externally changed you can see in here let's say Foo has the age of 20. I can go in here and say food at age plus equal to 10. and with this syntax I'm pretty much changing the age of Foo so if I then go to full age it should be 31 in here so you can see it's a variable that can both be externally Lee and internally changed all right so if you mark some a property as VAR inside a class however you can also Mark a property as VAR however allow that to be only internally within the class changed okay so let's say class person two so then we say private set VAR H ins so by by using private sets we're saying that only can be set internally inside this class implementation and can be read from the outside all right and then we say we initialize it with an H of int then we say self H is H all right and then we have a function in here we say increase increase age and we say self-age is equal plus equal one so we're basically saying pretty much the same logic as we had before but you'll now see that you cannot change this age from outside this class implementation so let's say Bas is equal to person two and then we say 20 here then we say bad H Bas dot h if you then try to change this externally you will gain an error simply because this property is not settable from outside you can see it can't be mutated all right now if you remove this private set from here you can mutate that age from the outside as well all right you can see it's working as expected but if you have the syntax private set then it can't be modified from outside the class implementation itself however you can use still this function which then modifies that variable internally so you can say bads increase age and then passage you can see now H should have been changed to 21 at this all right so that's the Syntax for private set in classes in Swift now you can also I mean now that we're talking about about classes very important that we talked about initializers as well because initializers are very very special I would say in Swift in that you can have convenience initializers and you can also have designated initializers now designated initializers their goal really is to is to ensure that they construct an instance of the Class by first of all ensuring that all property values are set and also that the internal structure or the internal validity of that class holds up however you can also have convenience initializers meaning that the only thing they do is that they probably add some logic to the Constructor or the initializer of that class but they essentially at the end of the day delegate the initialization to a designated initializer so it's as if you have for instance a you have for instance your mother in the kitchen or your father in the kitchen there is a party and they're making food and then you stand at the door of the kitchen as kind of like a delegate and people come and make their uh make like they basically make their order they say could I please have this then you can talk to them you'd be like let's say someone comes to the door the kitchen says could I please get a cup of tea and then you can say oh dude does it have to be red tea or does it have to be a black tea then they say oh red tea then you go to your father and say could you please make a air blah blah so I actually forgot whether it was black or red that that person decided But whichever they say then you go to your father and ask or your mother and ask them to make it so you're kind of like a delegate you're making the job of your father or mother a little bit easier and that's exactly what a convenience initializer does it gets rid of some Hassle and then at the end of the day it delegates the work to a designated initializer so just the designated initializer is the person in the kitchen and the convenience initializer is you at the door okay but let's have a look at some examples of how this actually works in real life so let's say class Tesla all right then we say let's manufacture my manufacturer server is Tesla then we say let's model is a string and let's year is in so the year production all right then um we will initialize our test line here we we create a designated initializer you can see in here is designated it doesn't have convenience written before it and we'll talk about convenience soon but any initializer that doesn't have the word convenience before it is a designated initializer and classes can have multiple designated and multiple um convenience initializers all right so here's a designated initializer and we say here model is X so let's say by default anyone initializing Tesla without passing any values to us they get a Model X Tesla and then we say year is 2023. so that's one designated and designated initializer the next one we will say init and in this designated initializer we actually take the model as a string and the year as an integer all right so we say self model is a model and self.year is a year all right like that now another property of designated initializers is that they cannot delegate their work to another designated initializer so in here you can say self in it model X and year is 2023 so we should get an error in here saying that a designated initializer cannot delegate its work to another one okay you can see it cannot delegate so designated initializers should do all their work themselves they cannot rely on another designated initializer okay so that's for designated initializers now let's have a look at a convenience initializer now let's say that you want to create a convenience initializer that by default assumes that the year is 2023. so the caller to that initializer doesn't have to pass the year all right so then you say convenience initializer or sorry init and then the only property we want in here is the model all right and in here then you can say this function calls the self in it with the model that is given in here but the year is 2023 by default so you can see a convenience initializer is delegating its work to a designated initializer in here okay now you can go ahead then and create a subclass you can say class a Tesla model y all right and it is subclassing Tesla and in its in it then what you want to do you want to create an initializer for model y that by default calls the super initializer and sets the model to Y and sets the year to 2023 all right or perhaps it could just call this convenience in it in here as well let's have a look so you create an initializer and here you say Okay I want an init all right however you need to be careful because init is already implemented on the superclass right here so if you're also creating an in and in your subclass you have to pre prefix it with override so you're saying I'm creating also another version of this okay and you can see it it says you need to at the end of this initializer somehow call Super in it so then we say okay then we call Super init and for model we say model Y and year is 2023. all right let's see what happens in here okay so now this should actually work as expected this shouldn't give you any errors all right let's see what happens if you comment this out and just instead call one of our designated initializers so sorry our convenience initializer which is this guy right here we just passed the model since the Year is already set to 2023 in this convenience initializer we could just try to call it and see what happens so I'm just going to say model is y all right and right here since this is a designated initializer inside a designated initializer you cannot call a convenience initializer from your super super class so this is another rule that you have to remember so I think a good rule to remember is that designated initializers in subclasses they can only call to designated initializers in their superclass inside any class a designated initializer cannot delegate to any other initializer okay convenience initializers can inside subclasses and inside their own classes call either and no basically not either but they can call a designated initializer okay it is a little bit special I'm completely aware of that but it's just some rules that Swift has set and I think logically they make sense but kind of they can make programming a little bit difficult sometimes when you're working with classes so let's let's create an instance of this model y so we say Tesla Model Y and in here you can see we don't have to pass any values to the initializer simply because we already have an init with no input values basically no arguments okay then we say model y oops model y dot model and model y that year and then model y dots manufacturer which comes from the superclass which is always set to Tesla all right now one thing that I mentioned at the beginning of the section was that classes are reference types they're not value types unlike structures and that should really make you aware of passing instances of your classes to functions so let's have a look in here let's create a foo bar and we say it's an instance of person two all right with the age of 20 in here and then we say Fubar dot h and then let's say that there is a function that is looking harmless it's called do something all right and with person and we just pass person two instance to it what this guy does internally is that person dot increase age it calls increase age function on that person all right Fubar is at the moment having the age of 20 and then if you say do something with fubar and then say fubard.h you can see the age will have been increased to 21. and simply is because the reason behind it behind this is that classes are reference types meaning that by calling this function and passing an instance of your variable to this function you're not copying the values of food bar over as new instances except you're actually passing your entire memory space Sorry the memory and allocated for your person 2 instance into this function so this function is completely free to do anything it wants with this person instance so just be a little bit careful with that just know that classes are a little bit more special than structures with structures you get a little more safety so to say now another concept and that we're going to talk about before we close off this section of the video is de-initializers they're quite useful in some special cases but some other cases you probably don't need them so I would say probably 90 percent of ties are working with classes you don't need the initializers unless you're working with some sort of notifications or RX for instance and yeah if you're working with reactive programming so let's have a look at the initializers as their name indicates they're kind of similar to initializers but they do the opposite the initializers are invoked automatically by Swift whenever your class instance is going out of memory so it's kind of getting cleaned from the memory so no one else is holding on to it and it has to be removed from memory so let's create a my class in here okay then in the init and we will just say initialized and then we'll have a function here called do something which which is empty at the moment all right then we create a new function in here called D in it and you can see that it is purple in here but it doesn't matter I mean the color doesn't really matter it just matters that this is a reserved word it's a keyword in Swift meaning that you can't really use it anywhere else except if you do something like funky like that but just know that there's a reserved word it's it's similar to in it but it's just called when your class is going out of scope and in here we can say d initialized all right now to test this we should actually create a function in which we create an instance of this because if you create an instance of your class in here let's just say let's my class is an instance of my class and then my class do something where the initializer won't probably be invoked you can see your initializer is invoked uh do something I mean in here we could actually say do something just so that we see that that function is also invoked however Danish Lancer isn't embodian that's just the nature of uh of playgrounds so what you could do is to create a closure my closure and we say it is this it is basically carrying out this logic inside the closure and then we can call our closure so at the end of this closure this variable should go out of scope meaning that it's the initializer should be called so let's say my closure in here all right and then you can see your D initializer oopsie Daisy what happened my closure uh all right cannot find my did I spell it incorrectly like this and now you can see that the initializer is in fact called and invoked simply because after my closure is called this scope completely finishes meaning that all variables inside this scope should also go out of scope so dnits will be called on all class instances all right really good we seem to now be done actually with classes so um let's just jump right ahead into the next concept and that is protocols so I'm going to go in here and actually not there we don't have to go there I'm just going to press command n in here create a new playground and we're going to say protocols again ensure that it is inside your workspace and in not inside another playground create all right and we get rid of this Explorer in here and we say Foundation like this Foundation all right now protocols for those of you who are rust developers you probably already know what protocols are and Protocols are special kind of objects kind of like interfaces you could say in Java for instance I'm not sure the term in kotlin what that is but you also have protocols as mixings in Dart for instance so what protocols are is that you create an interface you create a set of rules that objects which conform to a protocol have to follow so it is not a class and because if you have a class for instance if you have a super class that has some functions all subclasses do not have to re-implement that function however if you have a protocol that only creates some functions with no body so the functions don't have logic in them any object that conforms to those protocols have to implement those functions by themselves all right so it is actually a little bit difficult to explain what protocols are without having a look at how they work so let's go in here and say that this is automatically running and create our first protocol so we create a protocol called can breathe okay and in here we say any object that can breathe should have a function called breathe so you can see this function is special functioning it has no body you cannot create for instance a class person and just have this in it this just won't work you have to have a function body and you can't do that either in structures your function has to have a body so you can see that won't work in structures either that's why Protocols are a little bit special in that they can have just function declarations without any implementation all right and that's what is called interface insomni in so many other languages all right so we have a protocol now can breathe let's go ahead and create a structure called animal and we saw when we when we were talking about structures that structures cannot have super classes so they cannot actually inherit from each other okay so if you create for instance a structure of animal and then you say struct cat you cannot say that cat is an animal it just won't work structures don't allow inheritance however they do allow inheritance from protocols so you can say a structure of animal that inherits from can breathe and this is completely fine Swift syntax however we're getting an error because now you can see it says the animal a type doesn't conform to protocol can't breathe and the reason behind that is that a protocol here called can't breathe specifies that anyone conforming to this protocol has to implement this particular function and we haven't done that so as soon as we go and type breathing here you can see then this error will go away because now animal uh character conforms to Cambridge protocol okay and in here we can just say animal breathing like this okay and also then you can create another structure struct person can breathe like this and in here we say breathe as well and then we say person breathing like that all right so then you can go ahead and create instances of these two structures we say dog is an animal and we say dog breathe and then we create a person called Foo an instance of person we say the food breathe all right now you can see both of these lines will then be invoked uh simply because we call them from here so that's basically the essence of how protocols work I mean protocols can be a lot more complicated than that actually uh in that I mean we talked right now about having protocols that only have function declarations but not implementations but protocols and Swift are kind of like mix-ins and dart in that they can't actually have their own implementations so they're not just like objects that have dummy function headers but they can indeed have function implementations so let's have a look at that let's create a protocol called protocol can jump and then we say a jump function all right then in order to create implementation for this function I mean you may be thinking okay maybe I should do this jumping and this will just give you an error because you cannot create your function body inside the Proto call itself the trick to do that is to go ahead and create an extension on can jump okay and we haven't talked about extensions yet but it is necessary that we just name it in here simply because that's the way to actually add implementation to this function all right then we go and say okay it's the same function and then we just say jumping so by this trick you I mean it's not really a trick this is the way to do it by using this uh technique I'm trying to avoid saying trick by using this technique you're adding a default implementation to this otherwise very dumb function so you may be asking okay but what happened here can I just call this function now so can I just say can jump is an instance of can jump can I do that well you can't because you cannot instantiate a protocol you need to instantiate an object that conforms the protocol okay such as a cat that can jump so let's say struct cat and jump and now since this jump function already has an implementation you can see that we're not getting an error from Swift saying cats should implement this function if you remove this implementation from here all of a sudden all objects that conform to can jump need to implement this jump function themselves but if you bring it back into can jump then all objects that conform to that protocol will get this implementation by default but they can go ahead and change it if they want to like this okay so that's also valid however if you leave it it also works with that problem so let's create an instance of this cat we say Whiskers Whiskers it's an instance of cat and we can just say whiskers.jump all right this is how we can invoke that function that is implemented on can jump right now protocols apart from defining function headers that they're conforming objects have to implement they can also Define variables let's let's go ahead in here and say we have a protocol in here we say protocol has name protocol has a name and then in here we say VAR name a string and then we have to say gets in here or set or both like this now what this really means is that this protocol is asking Swift saying any object that com conforms to me has to have a variable called name that has to at least have a getter what does this mean well this is really just a dumb way of saying this so it it basically says a variable that at least I can read from but this syntax isn't valid and protocols I wish it was but you have to implement them like this so you're basically saying a some sort of a variable that I can read from which is called name all right and then you can also have H all right and let's just say h should be getter and Setter meaning that it should actually be a variable that can be set all right now we can go ahead in here and say we have a struct of dog and it has a name you can now see that we'll get an error now from Swift saying that this doesn't conform to has name and we can ask it to fix it for us and you can see by default it creates these variables for us however what I really don't like about this is that what it did is that it created a variable for name so it could actually be a let since the protocol has name asks for this variable to be at least and at most actually in read-only so we can just demote this to a let's variable and you'll see that everything will work as expected okay so let's go ahead in here and then create an instance of this dog and we can call this instance woof let's say woof is an instance of dark and we say name is with an H is a very graceful ten then we say with that name all right and with that H wolf dot h plus equal one so we just increase the age but we cannot change the name all right so let's just woof agent here as well so let's see what happens okay and this I mean we're getting these errors right here because we can't modify woof because it's an instance of a structure which by default becomes a left constant that cannot even have a mutation internally so we have to change this to A4 so remember structures are different from classes all right so this is basically a protocol that required all its uh classes or structures that conform to it to have a variable call name that can at least and at most be read from so it can be a let and it can also be a VAR but why does it have to be a VAR a promotion of let if we don't have to have it as a bar because the protocol says I should just be able to get from it now you may be thinking okay but why do we do these things well the reason is if you want to go ahead and add functionality to this protocol then this protocol internally has access to name and age let's say extension has name and then we can then create a function that says describe me then we can see we can say you your name is name and you are age years old okay so since this protocol expects a name variable and an age variable and it can then go ahead and read them so it can access them and it should also be able to set them okay and then you can say func increase age and in here then you can say self h plus equal one and we can fix this actually now so you can basically go ahead and add functionality to your protocols let's say fix it and we add a mutating function in here so you can see this protocol since it knows what it requires all its uh classes and structures that conform to it have to have these values then it can go ahead and take advantage of those variables or functions or whatever it has okay so now all of a sudden all objects are conformed to have has the name protocol will get a describe me function let's go ahead in here and say woof you can see it has a describe me function all of a sudden and it will say oops okay here your name is woof and you are 11 years old okay and maybe this should actually return a string and it could just return that string instead of printing it here and in here then we get the result you can see it says your name is Wolf and you're 11 years old and then since we have a VAR with uh pointing to a structure we can go ahead and say woof dot increase age and then we say wolf h all right so the H by this point is 11 and then we in we invoke this increased age function which is mutating function and then we get the age of 12 all right so protocols can Define kind of um constraints or kind of like an interface on objects that conform to them and therefore can using extensions on those protocols can access those variables and functions which are placed in here so it's kind of like giving a blueprint so it's kind of like any object that conforms to me has has to have this blueprint and then I can internally use that blueprint to my advantage okay now just we've just like we've seen this in here protocols can have mutating functions something that I want to mention next but I think I just mentioned a little bit too early perhaps but at least you get the point let's now focus on that mutating function so if you say protocol vehicle I just want to show you another example and let's say we have a variable speed and we say it should be an integer which is getter and Setter so we should be able to set it and read from it okay then we create a mutating function here increase speed and we say buy which value like this okay so we Define this mutating function here and then we go ahead and extend this vehicle like this and we implement this mutating function all right so what we did here was a little bit um is not optimal because we implemented a mutating func increased age inside the extension so whoever looks at our protocol won't immediately understand that there is a mutating funk available on it so if you wanted to make this code a little bit more readable we would place this function a declaration here as well okay so let's go in our code again and we say in the implementation of our protocol increase speed by value will actually have an implementation that's a self.speed is plus equal to Value like that and we can bring this value down here to make the code a little bit more readable as well and perhaps decrease the size of the preview as well so let's then go ahead and create for instance a a concrete implementation of this vehicle protocol so we say struct bike and then bike it will have a speed oh let's actually move this and say it is a vehicle all right then we get an error from uh Swift saying that it doesn't conform to Vehicles simply because it didn't have the speed variable then inside this bike we create an init and we say self dot speed is zero you could have also done it like this that also works it kind of depends on how you like to implement and do your implementations I've seen both and for me both are fine it's up to you and your team to actually make a decision on what uh can what convention you want to use for initializing your variables and structures okay but this is completely valid syntax as well after doing that let's create an instance of this byte let's say bike is an instance of bike like this then we get the current speed it should be zero because that's what the initializer did then we say bike increase speed by 10 and then we say bike speed all right so because we are conforming to the vehicle protocol we can have access to this increased speed function in here now I can see we're getting an error simply because a bike cannot be mutated you can see we're actually invoking a mutating function on an immutable let constant and the solution to that is to change this to VAR all right now you can see our speed was zero and then it was increased to 10 simply because we increased it using this mutating function defined and implemented on the vehicle protocol all right so that's one thing I mean that's not one thing that's quite a lot of things about protocols but at least you get the idea of protocols now protocols can also be used as a conformance uh how do you say it blueprints kind of so let me just explain how this would work you can at any point in Swift use the is syntax or a keyword in order to check whether an object conforms to a protocol or not because any class or any structure can conform to at least one and actually not at least at least zero and at most unlimited number of protocols so a structural class doesn't have to conform to any protocol or it can conform to one or more protocols that's what I'm trying to say and if you want to at any point check whether an object conforms to a protocol you can use the is syntax let's have a look at that let's say we create a function called describe and it takes an object of type any and we haven't talked about this before but any is pretty much as its name indicates any object okay then we say if object is a vehicle then we say uh object conforms to their vehicle protocol else object does not conform to the to the vehicle protocol all right then we can go ahead and call this describe function and describe our object of bike and then you can see since by conforms to the vehicle protocol then we get this printed to the screen however if we had a structure of warm or at work warm and it didn't conform to the vehicle protocol and we sit warm as an instance of warm and then we just say describe more then you can see that we will get this message printed to the screen object does not conform all right so now that we've done that let's just remove this warm I don't like to have worms in my coat so at least you get the point now with with that as well now there's one more uh one more thing that we have to talk about when it comes to protocols and that is I mean we've talked about is but we haven't talked about as and as with a question mark and they make more sense when we when we've already talked about optionals and we haven't talked about optionals yet we'll talk about optionalism in like the next three sections of this video but I just want to name it as well so you know that it exists in Swift so using this as syntax you can conditionally promote an object to a specific type so in here you can see object is vehicle and if you say object dot you don't have any anything to do now with this I mean you cannot do anything with this object even though you actually said if object is a vehicle then I kind of would expect us to be able to invoke these functions on that vehicle because we actually asked Swift is it a vehicle then we come here but Swift doesn't understand the syntax as good as it understands as like this and the reason behind that is You're simply just doing an if statement in here saying is it that then do something but you didn't actually promote this object to that type all right so any is like a very low object type however this is sitting a lot higher in the hierarchy and that's the reason we say promote so let me actually show you an example let's say that we have uh that we have let's say a bike in here and bike is a vehicle which has increased speed all right but we want to create a function that that can allow any object to come in and if that object is a vehicle kind of like this then it will increase its speed by 20. all right so let's say funk increase speed if vehicle and then the parameter to this is an object of type any all right then in here we say if then we create a VAR and the vehicle is equal to this object and then we say is it a vehicle like this with an as syntax if it is then we say vehicle speed you see now we get access to all properties of that vehicle because we promoted this object to a vehicle so it's not similar to is because this won't allow us to access the vehicle objects and hear our Properties or functions then we say get the current speed vehicle increase the speed by 10 and then get the speed again in here okay otherwise we say this was not a vehicle so let's then go ahead in here and see what happens so let's say increase speed if vehicle and then we pass our bike in here all right let's see what happens are we getting a lot of Errors perhaps from Swift it crashed no okay so you can see we got the value of 10 in here okay and then we get the value of 20. right here okay now you may be thinking about what happened in here bike let's have a look at bike you can see its speed it was zero in here and then 10. and then we call this function which should have increased the speed to 20. but if in here we say bike speed what happens do you think it's 20 well no it is 10 actually and the reason behind that is that bike is an instance if you go back to it is an instance of a structure called bike so it's a structure structures are value types meaning that when you call this function with an instance of your bike you're not actually passing the memory consumed by this bike as a reference to this function what are your what are your in fact doing is that you're making a copy actually not you directly but Swift is doing it doing that Swift is making an entire copy of this is making a copy of this entire object and passing it in here so in here this VAR actually is pointing to not the same memory address that bike is consuming but it's pointing to a completely new variable in the memory and is allowing it to basically be increased by a certain speed which is not affecting the spike however if this bike was an instance of a class so if we went in here and said bike is actually a class let's say class now you can see calling this function it will actually change the speed for you to 20. so calling this function it affects the actual instance of bike itself see the speed is exactly the same but if you go back to a struct you can see the speed of your bike will be 10. all right so keep that in mind when you're working with protocols protocols and classes and structures together go really hand in hand to create amazing object oriented applications in Swift but they can make things also a little bit complicated so keep that in mind when you're working with these um with these Concepts good that's quite enough about protocols now that we've talked enough about protocols let's go ahead and talk about extensions you've already seen examples of extensions and how they work in Swift but we haven't really focused on them so let's do that now let's go oh I don't have to do that let's create a new playground playground and in here we say blank playground and we say extensions all right like that and here as well then we say create and just like usual we say we just need foundation for now all right so extensions as their name indicates they can add functionality to existing types they can extend existing types so let's have a look at an example let's say that we have an extension on data type of integer and then we say we have a function called plus two which returns an integer and since this function is an extension of int self in here refers to the current integer instance okay then we say we return self plus two all right then we can go ahead and say 2 is equal to value of 2 and then we say 2 plus 2 and then you can see then we get the value of 4 here in our playground okay so self inside extensions refers to the current instance meaning that this two in this case all right so self in here is actually two so if you just print self and then you say return self self plus two you can see self is indeed the value of 2 in here which is what you've specified here so if you change that self will change to that as well all right so keep that in mind that's one example of an extension Now using extensions you can also add initializers to existing types which is one of the most powerful features of extensions in Swift let's have a look at an example let's say that you create a structure called person in here and you have a first name string and then let's last name last name as a string okay now what you want to do is to create a I mean you want to behold and sorry you want to hold on to this person's Constructor or initializer that Swift already creates for you with the first name and last name so you don't want to change that but you also want a Constructor that takes in a full name however if you go in here and say init full name screen then you can see all of a sudden your person doesn't have any other Constructor with a first name and last name anymore your only Constructor inside the structure itself will replace the existing Constructor okay and that's not good so what you want if you want to for instance have a Constructor initializer on this person that doesn't replace the existing in initializer that Swift creates for you then you need to create an extension on person and then you go ahead and add your initializer in here okay now you can see if you try to initialize an instance of person you have both of these Constructors the default one that Swift created for you and also your own Constructor which is inside the extension all right so let's inside this Constructor go ahead and grab the components out of this full name so we say full name components is a function and we separate the components by space all right and so we say let components and then we want to pass these values that we extract from components so we say self in it into our Constructor then we say the first name is actually components first otherwise fully and we say in here as last name is components last otherwise fully just like that all right so this is very dumb implementation to be honest with you but I mean it's not too dumb either it is literally taking the first part of a name and the last part of a name assuming that this is the first name and this is the last name and anything that is between them separated by space is the middle name which we don't care about in this instance okay then we can go and create an instance of person so left person is a person then you can see we have both Constructors or initializers and we're going to use full name in here we say Foo and bar you can see they're separated by space and the first component is Foo and last name and last components bar then we say person first name and person dot last name all right so that's another powerful future of extensions in Swift in that you can extend an existing structure for instance and add a new Constructor or initializer to it okay now apart from that you can also extend existing types and add conformance to a protocol to an existing type so that's also really cool so let's create a protocol in here we call it Goes Vroom okay so that's our protocol name and this protocol what it does is that it has a VAR room value and it's a string and it should we should be able to read from it okay and then we create a function we say go vroom and then this function returns a string now we go ahead and extend our goes room and then we add the default implementation for this go vroom function and then we say self Dot vroomvalue goes room so remember this is just a variable that we know any instance conforming to our protocol should have access to and then here we're just adding the default implementation for this code firm function and returning this string as its return value all right then we go and create a car instance we say struct car and this car conforms actually we don't want to conform yet and in here we say let's manufacture is a string and we say let's model is a string as well I guess this is just a simple car structure then we can say let model X is an instance of car with the manufacture of Tesla and its model is going to be X and after creating this instance we can go ahead and actually extend this model X so we can say model X extension sorry extension of car then we say car now all of a sudden conforms to the Goes Vroom protocol you will get an errand here telling you that you're not actually conforming to go Gold's room and the reason behind it is that if you go to ghost room you can see that we have two requirements one is that we have any type conforming to goes from protocol has to have a variable called room value that's at at most and at least readable uh however Carr doesn't have that and that's the error that we're getting in here so let's just get Swift to fix it and you can see it creates a computer property in here called vroom value which should return a string okay and for our vroom value we're going to say it is self manufacturer model and self.model all right and then all of a sudden this car instance conforms to That Goes Vroom protocol meaning that this model X all of a sudden gets a function called go vroom and if you do that you can see it says Tesla Model X goes room and that's because vroom value is a variable that is implemented on all types that conform to God's room but ghost room doesn't really know what this value actually is it just extracts that value and adds it here and then says goods room however it is the conforming types responsibility to return this value and in this case the case of car structure we're just saying manufacture and then model X so it says Tesla Model X goes through this part is provided by conforming types such as car and this part is provided by the ghost room protocol itself okay so you can also have I mean now now that we've talked about that let's go to the next concept and that is having extensions on classes and with convenience initializers so you can actually extend existing data types and add convenience initializers to classes and not structures because structures don't have convenience initializers but classes can so let's go ahead in here and create a class and we call it my double so like a class that holds on to a double variable and we say VAR value double and then we can say an initializer that takes a value of double and we say self value is value in here okay now you can go ahead then is actually this I don't think this needs to be a VAR it can just be a let perhaps okay and in here then we're going to go ahead and create a convenience initializer and which always sets this value to zero if anyone initializes the instance of My Double because at the moment if we say let let's go ahead Foo is my double you can see that you always have to have a value available and pass to my double initializer but if you don't want to have that you can extend your my double class in here and say you have a convenience in it in here that takes no parameters and calls self in it with a value of zero so this is literally delegating its task to a designated initializer in the my double class but it is a convenience initializer that is created inside an extension so you that's one of the powers of extensions you can extend an existing class and add a new convenience initializer okay so then you can go ahead and say my double to create an instance of it and then you can just say value all right you can see now the value is zero this is another fancy way I'm of basically accessing the value you could have said let my double is an instance of My Double and then you could have said my double dot value so that those two lines of code work pretty much I mean achieving the same thing okay now apart from extending I mean not apart from but I mentioned that extensions can extend structures and classes but guess what they can also extend existing protocols so so you can see in here we have a protocol called ghost room and it has this go room function you can go ahead and extend it you can say extension goes room and then in here you can add a new function say go of room room even more okay so this is just a ridiculous name I'm completely aware of it but you can um what I'm trying to say is that you can extend an existing protocol as well and add new functionality to it and by doing this every data type that conforms to that protocol would get your new function by default so you don't have to do anything okay then in here we just say self room value is vrooming even more like that okay then all of a sudden model X that we created in here which conforms to which is an instance of car which conforms To Go's room gets this new functionality by default so then we can say Model X go vroom vroom even more and then you can see that value being printed to the screen as well is rooming even more okay so extensions are I would say one of the most fun aspects of any programming language and in Dart for instance they're called mixins as well and they're available in some other languages such as rust as well so they're really fun because they allow you to make existing things and types better they can kind of get out of hand sometimes if you're like misusing them in that when you're extending generics types for instance you can just go crazy with generics but as long as you're comfortable and you and your teammates are comfortable with those extensions I would say go for it now we've talked enough about extensions for now at least let's go ahead and start talking about generics which is a topic a lot of developers try to avoid but I think you need to embrace it because if you look at most modern toolkits and Frameworks such as Swift UI they could have not been made possible without generics Swift UI is pretty much based entirely on generic types so I'd say one of the best practices of becoming a better developer is to embrace generics learn how to use them learn how not to use them and truly don't be scared of them so practice practice until you get the concepts and then use them wherever you think and your teammates think makes sense so without further Ado let's start talking about generic so I'm just going to press command in here and say a playground and we say generics like this and ensure you're creating it inside your workspace so Swift crash course and we create this generics uh playground import foundation and we say automatically run this all right I'm going to get rid of the export to the left hand side now generix is for me at least it's used to avoid writing the same function multiple times or writing the same code multiple times all right now generics they kind of look a little bit strange but they really at the end of the day once you've written the code for generics you can use them in so many different ways and you will be amazed by how powerful they are okay so what we're going to do as the first example of generics I'm actually gonna jump right in and write kind of like a scary looking function all right but what this function is trying to achieve is that I mean its mission statement is kind of like this it wants to expect any numer any numerical data such as a floating value or double value or an integer two of those values so it takes a left hand side and a right hand side and it expects us to pass it a function that can perform an operation on those two values and return a new value in response such as let's say x x is 10 and let's Y is 20 and then we say let's C is equal to X Plus y so this plus function takes a left hand side and a right hand side and returns a result which is the equivalent of adding those two values right now you can have minus in here you can have division in here it can have multiplication oops if I can write it so all these functions take a left hand side and a right hand side so they do some operations and they're actually operators we've talked about operators before okay so let's say then we create a function we say a function that performs a task and we say it's an operator that takes an integer and an integer and returns an integer kind of like this okay and then oops and then we say it performs this operation on a value on left hand side of type int and and right hand side of type int and then in itself returns int okay so you can see it's performing an operation that actually does the job I think they actually did something like this when we were talking about operators and we actually put this as a trailing closure I remember but it's similar to that at least and internally what it does is calls that op function and passes the left hand side and right hand side to it and returns this value in return then you can go ahead and say perform Plus on 10 and 20. and then you can see it will just say 30 as a result because this is actually a function all right and you can say plus and then you can say minus of course you can say multiplication in here and you could also say division in here okay so maybe we could say 20. and 10 in here for the division so that we get proper values printed to the console so this is an example of this function now your teammate comes to you and says could you make this function work with doubles as well then be like um okay then I'm gonna change this to double and this two double and then this to double and then you have to go and change this to double and this to double and this to double then your code kind of works all right but the result of these is actually now a double so if you look at Foods data type is a double what happened to your integers well you change the function signature from int to double and you lost the ability to work with integers then you'd be like okay then I need two functions one for integer m one for double then you call this perform int so we say let's see if I can change this name perform int and then you say okay I'm smart enough I go ahead and create a perform double and I make sure that this double works with doubles okay so whoever wants to work with doubles calls perform double and whoever wants to work with integers works with uh perform int then your third colleague comes and says okay but I want to work with CG float and which is another data type which is inside the core Graphics framework which we haven't worked with right now but you can say core graphics and then you can say let X is CG CG float is equal to one it's kind of like a double actually and then you say oh a CG float then I have to create another perform function which is called perform CG flow however as you can see this is not a very maintainable way of working so this will just increase the size of your code base and you have to constantly go ahead and add new functions to your application wouldn't it be really good if we could create a function that works with any numerical type and if you look at integer let's go to anything here and then we see signed integer and then side numeric you can see that this sine numeric protocol conforms to another protocol which is called numeric okay and if you have a double value let's say let's X is a double 1.1 if you go to double and let's say numeric there should be an extension on double extension double which makes it conform to a that's numerical type as well so let's say binary floating point I think and then expressible by Flo oops not that long perhaps by integer literal hashable so stridable it is one of these implementations which conforms double to add that numerical type that we were just talking about I'm not sure which one it is we have to dig deep inside Swift source code basically but what I'm trying to say is that both double uh and int conform to a protocol called a numeric numeric now if we could somehow in here say that this function works with any numerical data type that would be really good so let's change this to numeric and then we say numeric numeric and here here and here okay now you'll see what happens inside your sift code and Swift tells you okay I understand you want to work with the numerics but you can't just add them like that you can't just say that this function expects numerics numeric is a protocol and if you want to use it here you have to use generics so the way to use generics is that you go right after your function name and you just open these less than an equal signs kind of like in here then you designate a letter usually a letter but sometimes people use words as well but it is very very common to use a letter so you say Okay I want to represent numeric with a letter okay I can't just say new American here because that is an existing data type let's just say n okay as a numeric then you say n should conform to numeric data type or protocol then anywhere inside your function signature where you're using numeric just type n okay so in here in here right there there and also here and also for the return value of your function all right so now you see all of these errors are going to go away so you can see all of them went away and your function still works and if I say let X and then I look at the data type for X you can see X it is understood to be an integer but how you didn't say anywhere that you're working with integers and that's the power of generics the compiler is uh is basically inferring the data type based on the values you pass here so if you say 10 and 20 then it knows that they both are integers and the result should be an integer and let's change this actually it's not perform int anymore it is perform okay now if you go and do and let's say let's X is perform on 10.1 and 20.2 all of a sudden X is a double because compiler understood that oh these both values are actually double they're not integers anymore so it substitutes the return value which is indicated by this n generic value to the actual values you pass through this function in here okay and you can also go ahead in here and say 10.1 and 20 what do you think X is going to be now well the compiler is also intelligent enough to promote the value the return value to the more complex or more complete data type the more complete and precise data type in this case is not integer but it is actually double so if you look at the data type for X is indeed double all right so that was the first example of using generics in Swift and I know it could look a little bit complicated but the more you work with generics you the more you will actually appreciate them we've now seen this example I would say actually a quite a simple example of generics in Swift now when you have functions that have multiple generic parameters in this case we have just one generic parameter that we've called n of type numeric but in other functions you might have generic parameters maybe two two or three of them or even more in that case the function signature might be getting quite long you would say R is something and D is something else so looking at this function you you would probably just get a panic attack just looking at the function signature and that is why Swift allows you to create function signatures for or generic function signatures where the direct generic parameters are stated at the end of the function declaration itself and right after actually the return type so to demonstrate how that works as well let's just take this that we have in here the code that we have in here and let's go and paste it right there okay and we will just name this function and perform two and change all these instances to perform two just to ensure that everything is working as expected so in order to create a function or generic function where the generic parameters are defined at the anode function signature you have to remove this generate type right here or as many as generic types as you have you remove them from the beginning or attached to a function name and you go right after the return value and then Define them right there using a word clause so in here we then say where for instance n is numeric so this is an alternative way of creating a generic signatures for your um or for your functions and in here you would of course you would still have n in there but you don't actually tag and as a meaning of type numeric so this is just a an alternative way of doing it and some developers prefer this way simply because in here you could just say A B C D or your generic types and at the end you could actually say what those a b and c and d are in fact of type of all right so just keep it in mind it's it's a it's an alternative way of defining your generic functions and it will just perform exactly the same way it did in the previous example okay now any data types such as a class and actually I can't say any data but classes and structures in Swift can conform to multiple protocols they don't necessarily have to conform only to one protocol okay and using this you can basically create generics that are um that are conformant to multiple multiple types so let's have a look at that right now and let's create and let's create let's say that we create two protocols in here we say protocol can jump okay and then in here we have a function that says jump so any type that conforms to can jump should have a jump function and then we create another another protocol in here that we say can run okay and can run has to have a run function then we go ahead and create a structure in here we call person and we say it can jump and it can run like that all right so this is conform conforming a new structure to two different protocols we can get a swift to fix these functions up for us in here you can see in run we say running and in Jump we say jumping jumping okay I think the indentation was a little bit wrong all right now we have that now let's say that you want to create a function called jump and run okay so let's say flunk jump and run and you want to take in a value in here of some type you you want to say Okay I want some value to be of any type and in here I want to say value jump and value the run but since this value at the moment is of type any it cannot have the ability to invoke that function jump or the Run function so you could say Okay I want value to be of type can jump if you do this then you can do the jump function but you can't do the run function all right so in here what you need to do is to go ahead and Define a generic data type in here let's say t and we say this data type can run can jump and can run like this and then inside the function signature itself you say the value is of type T now you can see if you type value you have access to jump and run functions so this is a way of combining multiple protocols in order to create a generic function signature where you have access to not only one protocol data but also multiple as long as basically you can make this as long as you want to all right so then we can go ahead in here and create an instance of person we say person is an instance of person and then we can say jump and run with the value of person and we can actually change this values internal sorry external parameter type to nothing so we can just say jump and run person in here okay now you can also have extensions on generic types and one generic type that is very useful is actually we haven't talked about them so much about their arrays and I raise you to find them like this you could say let names for instance is Foo and bar now if you look at the data type for names you can see it is an array of string so it is denoted by these square brackets now you can actually look at if you just type this is a string in here and let's see if you can find the data type for array so if you say array of strings so this is this is a an alternative way of writing the same same text instead of this you can just do syntactic sugar here and say array of string now if you go to array you can see it is a structure and it is a generic structure basically it's working with a generic argument called element now you can also create extensions on generic types so by simply saying extension Offspring You're basically extending an array of string and this is new format actually there's a new syntax in the latest Swift versions previously you have to say extension array where element was equal to string so this is the old syntax but the new syntax you can just simply extend an array of string which is a lot more readable okay then what you can do in here since you already have you've told the Swift compiler that you're extending an array of string if you create a function let's say we want to create a function on our on any array of string that finds the longest string okay so we say longest string and we return an optional string we haven't talked about optionals yet so just for now know that this means that we can either return actually have we talked about options structures enumerations protocols extensions closures no we haven't yet we will talk about optional soon okay but just know that this means it can either be a value or it can be the lack of a value equal to nil all right so and the reason behind is that you can always have and the reason I mean this is an optional string is that any array like final names is an array of string in here it can actually be empty okay so if this array is empty how can you find the late at the longest string in this array well you can't there are no strings in here okay finally it should be let right so the reason this is optional is because of that and then what you can do in here is to say let dot um so you sorry you say self-sorted and this is I mean to be honest you don't have to know exactly how this is working and this is just an example okay so we say sorted and then we say left hand side string and then we say right hand side string and we want to say left hand sides count the number of characters in the left hand side should be more than the right hand size characters and then we say take the first argument you can see the first argument is then deduced to be of type string as simply because we are extending a generic type whose elements are of type string and if you look at this property you can see it is using the same generic type call Elements all right so that's also extending generate types and then you can go ahead in here and say let's say we create an array of strings we say Foo bar and bads in here has one string and then Cox in here then we say longest string all right then we can get the value of bar and pass it to the console or the playground console whatever you want to call it okay then we have another topic to actually discuss and this is this goes to a little bit more um I would say Advanced but I think generics are Advanced topics to start with so we shouldn't be scared of having a look at some Advanced topics in here so let's go ahead and talk a little bit about Associated types in protocols okay so and this is this makes generic protocols we've already talked about protocols before but we haven't talked about generic protocols so let me just show you an example and demonstrate how generic protocols work in the beginning it might not make so so much sense but as we go on and complete this example it will make hopefully more and more sense to you okay let's create a protocol in here we call it view all right so anything that can that can be displayed to the user and we call it just view all right we say any view should have a function on it that is called add sub View and it is basically using the same view so it says anything that's a view should be able to add on another view to itself alright then we go ahead and extend this view we say it we had the add sub view as a default implementation in here and we say by default it is empty all right so the end the default implementation of add sub U doesn't do anything then we go ahead and create a structure in here we call a button and we say it conforms to the view protocol and at the at the moment we say it its implementation is currently empty okay if we didn't have this default implementation of the add sub view function then button structure would have had to implement the add sub view functioning here as you can see suggested by the playground all right so let's remove these comments from here we go back to how we had it before then what we're going to do in here is to create a protocol and we say and we want to basically represent every object in our system that can be turned into a view let's say you have a struct person okay and then you say it has a name and then you want to say I want to somehow present this person on my user interface and then you say okay I want to make it presentable all right so you could Define anything in your system that is presentable as a View using a protocol let's say protocol presentable as view all right and this is kind of like hypothetical at the moment but later in this course we will actually talk about mvvm in iOS or Macos and watch us using for instance combine and Swift UI plus RX Swift on RX Coco but for now just this is a hypothetical protocol but it is very real actually I use this in production today so and I just want to give you an example of how this could look like all right now if you want to turn a protocol to a generic protocol you use a syntax or a keyword called Associated type and using Associated type is almost as if you say presentable ads view has some sort of a generic parameter but this syntax isn't accepted and so if you get an error okay you can actually see it says an Associated type name V must be declared so let's go ahead and Define this we say Associated type and we say view type should be any data type that conforms to the view protocol you see what we did in here we didn't just leave it empty we said if something is presentable as view its view should actually be be of type view all right so it can either be a button or it can perhaps be struct table here's a view all right and maybe this struck the person will conform to presentable as view and say that my you type is actually a table all right again this is hypothetical at the moment at least then we say any object that is presentable as view should be able to produce a view for us to display the user so we say produce view is a function okay and this guy should actually produce a view of type not view but view type all right so if your view type is for instance button then this function should produce a button if your view type is table then this function should produce a table then we can't go ahead and create the next function in this protocol let's let's just call it configure so we say anytime we want to present a an object as a view we can allow it to configure itself using a super view as its reference so super View and we say this is a view as well and we save this view is view type so we say the super view could be any view but this view oops type but this view should be is of type view type which is a generic parameter to this vertical okay and last but not least then every object that is presentable as view should have a function on it that is called present all right and in here we say view is view type and then we say on super view view all right so this view we're already sure it is of type view type because this configure function sorry this produced view function actually produces a view type and that same view will be passed to this percent function okay and a superview should be anything that is a few okay so that that was the X their protocol definition itself all right let's go ahead and Define implement it and basically do some default implementation for some of these functions inside this protocol so we say extension presentable as View and now this is a generic protocol simply because it has an Associated type all right then we go ahead and configure our we write our configure function in here so like that let's just paste it in here and we say it's default implementation is empty by default all right then we will have a we will implement the present function all right like this and upon presenting a view on a super view we just go to super View and we say add sub view view all right because we already know anything that is a view has this add sub view function on it so we just call it all right then what we can do to make this all very exciting we say we create a button called my button which is presentable as a view all right then we know that this function and this button has to have two function implementations and they're the remaining two functions actually we don't want to do that so you can see presentable as view requires four actually three functions it has a produced View and it has a configure Ampersand and these two functions at the moment have default implementations right here but the Purdue view function doesn't have a default implementation so you can go ahead in here and say that you want to Define produce View produce view okay and then we change this and we say this actually returns a button as we've defined it in here button is a view all right and according to our protocol implementation the producer has to produce a view type that conforms to the view protocol and button does that it conforms to the view protocol in here okay so inside produce view we just say we return an instance up button just like that all right now what's going to happen is that you don't have to implement anything else except for this but if you want to go ahead and for instance do it as configure function in here so as soon as you start typing it let's say configure you can see then a swift understood that super view is a view however this view is a button but how they didn't understand the answer button the reason is that we changed the implementation of produce view so that it produces a button then Swift went to this protocol implementation in here and said oh produce view is producing a button so everywhere in this protocol where I see view type I'm going to replace it by button so it did this pretty much button button and button you can actually go ahead and test that by adding for instance also at the present function in here you can say present and you can see superview the view is a button so that's how generics work basically in in Swift protocols okay so it's very very simple when you look at the whole thing but if you go into details you can actually see there's lots of things to learn about how generics work with protocols especially and Associated types so just know that for now that protocols can become generics using Associated types and sometimes in Swift you need to know about them and you need to use them but if you're not working so much with generics you probably don't have to bother so much with Associated types but again if you feel intimidated by generics and Swift I think you need to tackle that fear and go ahead and actually play with generics so much that you become so comfortable with them that it becomes a part of your day-to-day tool and day-to-day way of working with swift okay now if you want to extend generic protocols just like you have extension on for instance here and you can see we have extension on this generic protocol you can go ahead and actually constrain your generic extensions to specific types so let's say that you say extension presentable ads View and then you can say where view type view type is equal to a button all right this way you're training extension on any object that conforms to presentable as view as long as that object's view type is a button if you did this let's see what Swift says actually so we're just creating a simple extension Representatives view if you add a function to this any object that conforms to presentable svu's protocol is going to get your extension values and or variables and functions however this way only presentable as view conforming objects that have a view type of button will get your extension all right so let's say func do something with button so we are adding a simple function in here and we'll say this is a button all right then let's go ahead and create a button we say button is an instance of my button and since my button conforms to the presentable ads view protocol we can say button do something with button right however if we went ahead in here and set structure table is also a view actually let's go to my button and we will just say my button is we copy that code and we go ahead in here and we save my table okay my table and in here where we have button we create another struct and we say table is a view and we say it's empty as well all right then we go back in here inside our my table we say that my table produces a table and in here we just create an instance of table and we change this as well to table all right so and we can remove the configure function as well we don't have to have it in there now if we go ahead and say my table table is an instance of my table if you say my table dot you can see that you don't have access to to do something with button function if you want my table to have the same extension do something with button and first of all you'd have to change the name of this function so you say do something with view for instance with View and then you also have to remove this generic constraint from here because my table doesn't produce a button it actually produces a table then your table my table will have to do something with view function as well all right so I hope that this makes generics a little bit more clear to us at at least by this point now apart from all of this you can also as I mentioned like when we saw this extension on array of strings let's see where we did that longest string okay you can also create other extensions on arrays even though there are generic types such as for instance calculating the average value of an array of integers so you can say extension int so any array and that contains integers and then you can say a function that calculates the average values and we say double and then we say self reduce this is a special generic function on any array and you start with a seed value and in here you do your operation you basically what it does is that if you have values one two three four it says okay I start with the value of 0. then I go to your first element then I say 0 and 1. so then we say Okay Plus them together it says okay zero and one plus together will be one then I will take this one and I will go to the next element which is two and I will do this operation between these two one plus two is three it says okay then I have three then I go to the next element and say three plus three okay six six is here and this is I go to the next element six plus four it will be ten all right so this is how reduce actually works if you take the so basically this com if you say lip XXX and then in here we say XXX you can see it's an integer but we want to grab the average then we have to divide this with uh the count of this array so self.count and we have to convert all of these to doubles so that they can actually produce a double value in here okay you can see now it is quite uh happy with the code that we're written and then you can say one two three and four and you get its average all right and you can see then the value printed to the screen right here 2.5 all right so if you had an array that was just like two and two or four and four in here then the average would actually be the same value as you've entered in here 2 and 2 will produce two and four and four will produce uh four okay so that's how you can extend existing data types that are generic such as race okay I really hope that all of these examples made generics make a little bit more sense to you if they didn't I think it is important that you go back and practice generics yourself as well because without practice generics will probably never make sense good we're done with generics let's go ahead to the next section which is optionals so I'm going to create a a playground in here playground and we'll say blank and we say options which is also a very fun topic to talk about in Swift so let's just do that good and then in here we say import foundation and let's just do this so that it runs automatically as well and let's get rid of our project uh Explorer to the left hand side all right so optionals indicate a value that might or might not be present okay so let's say that you want to take a value and multiply it by two okay so let's create a function that takes a value and multiplies it by two so we say flunk multiply by two in here and then we say value and you can see it's an integer and it returns an integer as well all right then in here you just say value multiplied by two in order to turn this data to actually before I say in order to let me just explain what options then would do for this function and how they would make this function perhaps a little bit more fun to work with if you call this function multiply by 2 you always have to produce a value in here so you can't just call this function empty we're thinking that it will just produce zero if you don't pass anything to it okay you can see that it says okay you have to pass a value to me in here then if you don't want to do that if you just want to say okay if a value isn't there just assume it is zero okay what you could do is to say okay value is optional so you say it shouldn't it doesn't have to be passed on here and furthermore you can assign a default value to it so you say value is an optional integer that by default is not present then what you can do in here you say if let's value so this is the syntax of unwrapping an optional so you say if the value is present then return value multiplied by two otherwise return the value of zero like this all right and also there are other ways of actually doing this in Swift so you can see now this function works fine because it's hitting this point since a flat value syntax indicated that value is indeed nil there are other ways of doing this you could actually change this code to this and do it like this you could say it's an integer which by default is zero then it will work exactly as it did but I'm just trying to demonstrate how optionals work and how a flat works it's a little bit difficult to find hypothetical examples for using optionals which is a little bit a complicated topic to explain and even more complicated to find very trivial trivial examples of how to use them all right but let's just leave this example as it is so now you can see that you can call that function with either no value values or you could say you pass the value of nil and it will produce also zero or you could say you pass a value of 4 or 8 or whatever you want in here and this function will still work so even it works even with the value of nil I don't know why our playground isn't really running yet there we go so we got our values okay you can compare optionals with nil nil is a special value meaning that the absence of a value basically so you could say let H is an optional integer and it is equal to nil all right so it is not present basically then you could say if age is not nil age is there how odd because we expected it to not be there else H is now correct okay so we kind of expect this Branch to be to be executed right now and you can see that it is okay so that's how you can compare a value not being nil for instance okay now if you want to take an optional value and check whether it actually exists or not you should use actually not you don't have to use but you can use the if flat syntax so you say if let H if H is present then inside this block after if let age is not optional anymore so you can see it is right here okay so then you could say h is there uh how odd its value its value is H all right otherwise no age is present as expected because we know that age is actually nil and we should get this uh printed two that counts all right now apart from if let's way of unwrapping and optional you can also use another syntax which is called guard and guard does the negation of age basically so let's have a look at how Guard works so let's say we create a function in here we say check age all right and in here we want to read age we say we want H to be there if it isn't then we're just gonna return from this function within message but if it if it isn't there we return with a message but if it is there then we print something to the console for instance so you could say if age is nil then you could say age is nil as expected all right however there is another way of writing this function and the way to do that is you say this let's say that this entire function depends on this age variable right and however if you um if you type a function if you type your code like this anyone reading this code might not fully understand that this age variable is very important to this function's signature or dysfunctions functionality and that is why Swift has an alternative way of doing this check so if your function depends on some optional values and it can't really continue without those options optional values actually be being present you need to perhaps use the guard mechanism so in here you say Guard age shouldn't be nil else then you say age is nil as expected and then you return okay so you're basically saying make sure age is a nil if it is so this else reads if it is then do this and inside guard you always have to return so if you don't return you actually get an error so guards have this property that they need to return and because that's the whole point okay and also using guard you can unwrap values as well as we'll soon see so let's put this card in here and then we say the rest is age is not nil here strange because we don't expect that and then we call the check H function in here so we should now hit this Branch because age is indeed nil so we can't just guard that it isn't nil because it is nil and it will end up being here okay Now using guard you can also unwrap values because you can see in here if I say let XXX is H and in here I say XXX it is still an optional all right so um even in here if I select XXX as H you can see XXX is indeed optional integer however in here we said make sure that it isn't it isn't nil so it shouldn't be integer so I kind of expect XXX to be an integer all right but it isn't and the reason behind it is that we're not actually unwrapping this age we're just making sure that it isn't nil but the rest of the function doesn't understand and the way to fix that is to actually use garblet so let's say let's H2 int optional and we actually set a value for it we set a value on zero okay then we create another function here we say check age two and in here we say guard let H2 otherwise so if we go in here and say let XXX in here let's do a return and we say XXX is equal to Age Two you can now see XXX is an unwrapped integer it's not optional anymore and that is simply because we did a guard let all right and then here we say age is nil how strange and then we return and then in here we say Age Two is not nil as expected uh value is equal to Age Two all right so this H2 in here is not uh this Valley anymore really it is unwrapped within this function all right then we can call this function as normal we say check H2 check H2 and we should then hit this line in here and you can see the value of H is indeed printed to the console value is zero you can change it to 10 if you want to and you can see that value being printed to the console as well all right so that's another syntax for guard using guard let for actually unwrapping an optional now optionals are actually an instance of an enumeration this enumeration is called optional unsurprisingly so just like you can switch on option on enumerations you can switch on options so you can in here go ahead and say switch age all right and you can get help from Swift to complete these for you this search statement you can go in here and say fix it for me you can see this optional uh enumeration actually has two cases let's see if we can find it enum optional there we go and it either is the value of none meaning that it is nil or it has some value inside it all right so in case of none let's just say age has no value as expected in case of sum we can unwrap it and say let's say value and we say age has the value of value like this and we can break in here as well break okay so age was nil if you remember so we kind of expect to hit this casing here which is none and it says age has no value as expected all right so that's how you would switch basically on an optional value you can also go ahead and do simple comparisons so if you could say if H2 for instance is equal zero so you could do that then you say H2 is 0 as expected and it's not the nil and let's go to H2 and actually make sure that it is zero so let's change it to zero and in here we say else age to is not zero how strange all right and as you can see the comparison is working so you don't so what I'm trying to say in here you can actually compare an optional value with another value like this without having to say if K slat or is it let case or case let I I always forget that so you don't have to unwrap it using a case let's or using a switch you can just compare it with an unwrap value like this as well okay now you can also just like we did this comparison you can also compare with the non or some cases so let's just copy and paste that code in here then we say if H2 is equal to sum 0 and then you say the same code in here so this these two are equal to each other I mean they're not equal but they're identical to each other so it is completely up to you how you want to do this code and for me if I see this code I don't assume that ah2 is optional but is indeed optional and but if you write your code for me I completely understand that oh H2 is optional so this is a little more descriptive of the problem in hand so I actually would probably prefer this but it is up to you and your team to decide on a convention on which one makes more sense to you okay now you can also do optional something called optional chaining and and that means you optionally access optional Properties or methods of some classes or structures so let's create an example for it we say struct person and we say let's name the string and we say left address is let's actually not do that at the moment let's inside this structure create another structure called address okay and in here we say let first line is a string and it's optional all right so we if we have it at an address then this first line might not be present and also uh additionally we go into person in here we say addresses itself is optional so even if it is present it doesn't have to have a first line but if it's not present it will be nil all right so it's like optional within optional so this is optional within this optional actually the other way around uh address is optional and within it there is another optional property okay let's create a person in here we say Foo is a person and we say it is equal to an instance of person with the name of Foo and its address is nil we just say we don't have an address okay then if we say we want to get this person's first line of address then we say if let Foo first address line line is equal to Foo then dot address and optional optionally grab the first line all right so it means address is optional we know about that but go and grab its first line if it is present then we say um E flat okay is equal to that then we print it out through first line otherwise we say Foo doesn't have an address with first line as expected so since we didn't have an address for Foo at all then it shouldn't even have a first line okay so this address basically Swift stops right here it says I can't go any further after address because address it itself nil so I can't grab the first line of it even if first line did exist the address itself doesn't exist okay so then we get this message printed to the console now we can go ahead and do another like an alternative way of grabbing this value is by first grabbing the address and then out of the address grabbing the first line it is a little bit more code and I don't actually think you win so much on it so I just wanted to show you how you can do that as well let's say if let Food address is food dot address so you first unwrap the address okay and then you say okay after that get the first line as first line like this is equal to full address DOT first line then you can say Food address and then you say first line all right but we know that we don't get in here because food's address is in fact nil so we don't even go inside this code in here and not in here either okay now you can compare optionals using chaining as well so let's go ahead in here and Define a bar person we say bar is an optional person actually and it is equal to person whose name is bar and whose address is in fact an address instance with the first line equal to nil all right so it has an address but its first line is now then we say if bars and you see we're accessing bar using an optional like a question mark simply bar simply because bar in itself is an optional value if bars name is equal to bar and bars address first line is equal to nil then we say bars name is bar and has no first line of address okay otherwise then we can say um seems like something isn't working right because we know that Bar's name is indeed bar and it has an address what its first line is actually nil okay but do you know this line of code actually isn't saying that it has to have an address but its first line should be nil it could actually work as well it will work as well if the entire dress is nil so let's just change it to nil and you can see still the same code will be executed all right so that's how optionality works it just continues until it can't continue any further okay now you can also switch on options with word Clauses all right using an optional chain so let's create a bass person in here I'm just going to copy paste that code so we don't have to create many persons and this time it's an optional person with an address that is present and it has a first line as well all right then we can go ahead and say switch on the per on baz address first line all right and in case we say in case of a sum we say let at first line and we just break in here and we say case and none actually let's not do that let's just say uh case first line and then we can go ahead in here and add a where Clause so this is pattern matching and so we're saying okay if the first line is available and using this word clause is pretty much just saying and and the first line starts with uh the string baths okay then we say bad's first address line is equal to first line like that then we say case let's sum and then we say first line and we don't have a word clause anymore and this one catches all then we say Bass first address line that didn't match the previous case and then we print the first line all right and then last but not least we also have to cover the non case where the value the optional value is indeed nil we say bass first address line is new and weird okay because we already know that bass is first address line is in fact Bas first line and you can see this being printed to the console it says Bas first address line is bass first line as it was in here so you can have where Clauses in your case statements for switching on optional um enumeration or enum values okay now you also can choose to um if you're using a flat or Gauntlet and you should do that uh as long as it makes sense to you all right so let's create a function in here let's say we say funk get full name and then we say we have first name as a string and then we have a last name as an optional string and we produce an optional string as well all right then we say we say that you have to have a last name all right even though the function signature says optional we say that okay you should have one we said if let last name if we can unwrap it then we return first name and name and space then we say last name all right otherwise otherwise we return nil all right now that's one way of doing it so you can just in here say get full name and for first name we say Foo and for last name we say nil then we call the same function with uh Foo and bar as names like this so this one has a last name of Nils so it should end up being here and you can see it's actually producing the value of nil and this one has both first name and last name therefore it is returning Foo bar as this result so that's one way of doing it but you can also go ahead and use guardlet so if you copy this code from here and then we go and paste it right here we say get full name two and in here you could say guard let last name otherwise return nil and then you switch these statements basically all right so you basically the way I usually read this is like this make sure last name is present otherwise return and then do this otherwise basically saying if last name is present okay so after doing a guard let all statements after that card let if we hit them in that in those statements the value that you unwrapped in here will be present as a non-optional all right so that was also short and sweet about optionals and there's lots more to actually explain about options and they pop up pretty much everywhere in Swift and especially Swift UI Azure as you as actually we'll talk about Swift UI later in this course as well but just know that they're there you need to learn them if you're working with Swift and it is very advantages if you can really master optionals and suit because they're pretty much everywhere I hope you enjoyed this section of the course as well and in the next core in the next section we're going to talk about error handling in Swift now that we've talked enough about optionals let's first do some cleanup here in our workspace so I'm just going to press command command W and close all these tabs that we have opening here there are quite a mini and they're not really contributing to so much right now rather they're just like making our workspace look a little bit dirty so I'm just gonna do command W in here and if you're in Visual Studio code for instance on Linux and or even actually replace build build oh okay I don't know what happened really and even if you're on Linux and you're for instance having Visual Studio code open with your Swift files you can also close them if you're not really interested in having them all open at the same time so as mentioned we're going to go and talk about error handling right now so I'm just gonna press command n and say blank in here and playground and let's say error Dash handling and I'm going to create it in the main workspace in here as you can see okay let's press create in here here and say import foundation and like usual we're going to go in here and say that it should automatically run all our code okay so error handling is one of the most important Concepts in any programming language that supports errors and exceptions and really the points of errors and exceptions are to tell the the caller to our code or whoever is using our code that something has gone wrong it's either the failure of the code that we've written such as an error or it's the failure of the person calling this function or code such as an exception so there is a little bit of a difference between actually errors and exceptions in different programming languages but in Swift usually we only talk about errors so meaning that the code found out that something hasn't gone according to the plans and then it throws an error and actually the word for it is actually throw in Swift indeed so there's a keyword for it called Throw okay and it is the same thing in many other programming languages actually it is called throw in Dart for instance as well so let's have a look at an example of throwing an error in Swift and catching it so we're going to create a person in here let's see if I can spell struck person and let's say we have a first name uh it's an optional and we say last name optional string as well okay then we want to create a function in here called get full name and this function should ideally return a string okay so we're going to say funk get full name and we say it returns a string right however how can it return a string if first name and last name are both optional meaning that they could at any point both be nil or one of them could be nil and in those cases we cannot produce a full name so the goal of this function is to return a string it shouldn't really return an optional string because the full full name shouldn't be optional then what we're going to do in here we're going to say okay it is going to try to produce a string but it may actually throw so we say throws okay so the function throws but inside is it will throw all right so that's how the how the verb and the noun basically work uh actually I think it is a noun yeah so the function is marked as thirds meaning that internally it can throw an error now we're going to go ahead and Define our errors inside this structure then you don't have to Define them inside the structure or the class that throws them but it is usually good practice to Define them within their enclosing structure or class so so to associate the error objects with that structure or class okay so we're gonna go and say enum errors for instance it doesn't have to be colors you could call it Myers or person errors whatever okay person errors also works but in here we're just going to call it errors and we need to ensure that this enum conforms to this error protocol okay you can see it is a public protocol okay so you cannot throw errors that are not um actually your enum if you're actually going to throw its cases the entire enum needs to conform to the error protocol so that's their role basically that we're going to see the first case of the error is for instance first name is nil we're going to say then last name is no and we're going to say case both names are nil so these are the available errors that this function can throw so these are the three things that can go wrong either the first name is no or the last name or both in any other case means that name and last the first name and last name are not nil and we can calculate the full name successfully all right so as option as we've actually learned in the optionals section of this video optional data type is a it is an enumeration meaning that we can do switch on them so if we want to basically learn whether these two are both not nil you could either do it like this a flat first name and let's last name then you can produce the first name and like this first name and then last name this then you should say else if first name is nil and last name is not nil then you should say throw and you say errors first name is nil then you have to do a lot of else statements in here to understand okay first name wasn't nil last name was nil and then throw uh last name is no and if both of them are nailed then do this so it's a lot of if and else statements instead of all of that we can just do a simple switch statement in here okay so let's just say we switch and we say we switch on the first name and last name alright so this is the first name we're doing is switch on two enums at the same time all right so the first case and we want to handle one third both nil so we say case the first one is none and the second one is none okay in this case both names are nails so we say Throw errors both names are name the next case we want to make sure that um we want to basically see if the first name is nil but the last name is not milk so we say first name is nil and the last name is not mil remember sum and non-30 cases of optional so if you go in here do you remember these none and some some meaning that there is a value so we're saying that there is no value for first name but there is some value for last name in the case I'm not having a first name then we throw an err and we say first name is no then we reverse these so we say in here we take this non we say the first name is sum value but the last name is no values and then we say last name is no and in the other case then we say in the case of actually having a first name and last name so we say case let sum first name and some last name in here then we can calculate we say return and we return a string with the first name and last name in here just like that okay so this is this is like some sort of a pattern matching you could say in Swift and pattern matching in Swift is very powerful I mean I would say it's even more powerful than pattern matching for instance in Rust which is also in its in its own very powerful but Swift has some really neat features when it comes to power matching with switch statements for instance okay okay so let's go ahead now and create an instance of this person's structure we say let's oops can I spell let's Foo and we say person and for the first name we're going to say Foo and for the last name we're gonna say nil all right so now we want to go ahead and grab the lat the full name of this person and knowing full well that the last name is no meaning that we're gonna get into this case actually no sorry this case last name is no all right so how do we do that because if we go ahead and say let full name is uh Foo get full name get full name you can see that we're going to get an error from Swift saying that actually it's very important that we see this in error it says call can throw but is not marked with try it says Well it can't throw basically it can throw an error but you're not trying to resolve that error so the key word for trying to resolve I know or trying to actually call a function for instance that can throw the keyword for it is try okay so you say try however we're gonna probably get another error now and it says well it crashed so the entire playground pretty much crashed and the reason is that this function through but we tried this inside a inside a context that doesn't have error handling so if you're using try then you need to be inside a context in where in which you're handling your errors and that type of context is created with the do keyword so you say do and then you place this code in here okay and in here then you can go ahead and say catch and then you say got an error and there is an internal error object in here which is just called error okay and you can see now we are getting this in here and says God error and it says last name is no so this is according to what we basically expected okay so just remember do and catch and inside the cache block if you don't specify anything in here and like let's e or something because then we're going to get e in here if you don't specify how you want to catch in into which variable there is an internal hidden variable called error inside every catch statement okay good now if you also want to I mean this this just catches every error any error pretty much okay so if you go in here and say Foo and the first name and last name for it is nil now you see you catch another error that's called both names are nil okay but what if you want to catch specific figures you don't want to catch every error you want to catch for instance specific errors you can you can say I just want to catch person errors okay and any other error that happens in here I don't want to catch it because remember inside the do statement you can actually have a lot of code you can have a lot code in here and you can say let blah is try something else okay and any of these statements that have tried before them they can throw and they then those errors that are thrown could be of different types So within the do statement you can have multiple uh lines of code Each of which can also throw different types of Errors if that is the case how can you catch specific errors and the way to do that is using the is keyword after catch I'll show you so let's copy this in here that we have and paste it and then we put the full name in here just so that we get the full name printed to the screen if if any but we already know that there will be no full name and in here we're going to say catch is person.heirs I like this okay and you can see in here this statement is still I mean let's see here okay we're gonna get rid of this one because we already know that is a person error okay so we have pattern matching basically on our catch and we can't actually grab the variable out of it anymore so we we detected that it's a person error and then the error variable isn't available to us anymore after doing this pattern matching okay so this is how you would look for specific types of errors in your catch statements all right now you can also catch specific errors I mean here you're basically matching the error against a type but then you would be asking yourself well but how do I know which one of these errors it is okay and you can actually catch specific errors just by typing catch which error okay so let's copy this code actually maybe let's create an another variable in here we say let bar equal to person and in this case we say both first name and last name are nil all right like this then we're going to copy this code that we have in here and right after bar we're going to paste that and we say full name is bar get full name all right and then in here inside catch we're going to change this code that we have and instead we say catch person errors and a first name is nil then we say first name is no like that and then I copy I'll copy this and I say we also want to catch last name is no and we say last name is no then we say okay we also want to catch person dot errors both names are now and we say both names are nil and otherwise at the end we have a catch all Block in here let me say some other error was thrown okay so now this now you see you can we're basically getting this error in here both names are nailed as expected first name and last name or not are basically nil okay so this is how you can catch specific errors as well this is how you can catch air types like errors of this type but inside this we already know that we have three specific errors and if you want to catch any of those specific errors you can do do just catch and that that specific here okay so that's another way of handling errors now we've had a look just at one function at the moment that can throw but uh you can also do you can basically throw errors inside Constructors as well of structures or classes meaning that you try to construct an object but the parameters that you're passing to that object are somehow not valid and so as you know the Constructor or initializer of classes and structures have complete rights to do some validation on the data that you're passing to them if those data for some reason are not correct according to the validation of that structure or class then the class or structure should be able to throw okay and I'll show you now how you can Define throwing initializers or Constructors for structures and classes so let's create a struct car in here okay and then we say let manufacturer and this manufacturer is a string then what we want to do is to create a a Constructor or initializer for this car that looks at the manufacturer that you pass to us and if it is empty then it's going to throw an error because at the moment you can say my car is a car with a manufacturer of empty string and this is not valid according I mean to our rules you shouldn't have a card that doesn't have a manufacturer okay so we want to basically catch this case we want to see okay when you pass the manufacturer to the structure is it empty if it is then we want to throw an error so let's go ahead and Define that error first so we say enum errors and of course we have to conform to the error protocol and we say case invalid manufacturer it is a very complicated word to type in my opinion then we go ahead and we say okay we have an initializer in here which takes in the manufacturer okay so I'm just going to copy this so I don't have to type it anymore and then in here we say this init function and it or initializer actually throws and then we say if the manufacturer is empty then throw errors dot invalid manufacturer otherwise self manufacture is equal to that manufacturer okay so you can see then we don't have a problem in here the only problem actually we have is that we're now calling this now Swift understands that this call to the initializer of car is throwing but we're not trying it okay so let's go ahead and do a try on this so we say do and we say we catch car errors invalid manufacturer and we just have a catch Hall case in here as well so we go into the do and we say try this code and in here then we say invalid manufacturer and we say some other error just like this okay now you should be able to see that we get this invalid manufacturer and pass in here so now the important thing is also that if you're inside this do clause and after this try statement you can definitely use my car so you can say my car that manufacturer do whatever you want with it but you already know that none of this code is going to be executed because the way we're calling this car or the initializer of the car structure is that it's going to throw so it's never going to reach this code in here so Swift reads this code goes and calls the Constructor and it gets to this throw and just immediately jumps out of this into its catch statements and says okay do I have any cash that matches the error that was just thrown yes and it then comes here and it doesn't even go here okay so you need to kind of follow the path of the program to understand what is happening really now you sometimes may not really care about the errors that are being thrown from functions or initializers for instance and the way to do that is that you want to grab the value of a function optionally so you say if this function is successful gets me the value for it so you don't actually care about the errors okay so let's go ahead and have a look at the syntax where and syntax work is using a flat okay so you said if let your car is equal to try with a question mark so this is simply try with a question mark simply means that you don't have to have a do and catch statement it says optionally try to call this function and if it is successful then give me the value back okay so we say Tesla and then we have access to we say success your car is a your car like this otherwise we say failed to construct and error is not accessible now so if you do this statement in here so you can see we're passing Tesla actually to the Constructor for our initializer for car therefore this logic is not going to be called and and a proper instance of car will indeed be created meaning that we will indeed come in here inside the success block all right so we optionally try to call this function if it was successful if it didn't throw then we come here and then we have full access to this variable all right otherwise we get to this clause and as you can see I've typed in here in here we lose access to the error that was actually thrown so we don't have access to the error object really in here okay so that's how you can optionally try to call a function that throws and grab its value now you can also in some very rare cases very angrily try to unwrap a the value of a function that can throw please know that in in all my years of working with Swift I haven't done this I know that it is available but you you and you should as a swift programmer know that it exists but you should almost never ever use it but and the reason behind it is that this code as I said angrily unwraps a function that can throw meaning that your program or your application or your IOS app or watch OS app or Mac OS app will indeed crash completely and completely close should the function that you're invoking actually throw an error and the Syntax for it is not with an optional try it is indeed with a a how do you call this actually exclamation mark okay so let's go ahead and have a look at this we say let their car is equal to try and we say car with a manufacturer of Ford and you can see now this will indeed be a valid um car instance and I can say their car that manufacturer nothing really happened and you think okay but why did he say that you should never use the syntax and the reason is that should this manufacturer be empty this whole playground will crash and it will just you can see in here and encounter a crash and could not finish executing this same thing will happen to your app and what whether it's a Mac OS or iOS or and watch OS app your app will completely crash it won't look as pretty as it did in the playground because the playground it still was open but it just told you that it crashed if it is in a real application the application will just completely close and the user will be baffled by what just happened so please don't use the syntax try to always do I mean ideally you should do do and catch if you can't do that please do try and please never try this never tried this way of unwrapping values unless there is a very compelling reason for it that you and your teammates for instance are completely comfortable with okay now we've already looked at throwing errors from functions but just know that you don't necessarily have to throw a specific type of error in here we have just one enum and then here we also have just one enum that Define our errors but a any function that is marked as throws can't throw any error it doesn't necessarily have to throw a errors from just one enumeration so let me just show you how that will look like let's create a struct in here and we call it dog all right like this and inside this let me actually create some empty spaces so we can do this so inside the dog structure we're going to create two variables one is called is injured and is sleeping okay so it is injured injured Bull and uh let is sleeping in here Boolean all right and then we go ahead and we want to create two functions a bark function and a run function so let's say funk Funk bark and Funk and we say run now inside the logic of this dog structure we're gonna say okay we're gonna bark like this but we're only gonna bark if we're not sleeping all right so we're saying if is sleeping like this then we want to throw on air so let's go ahead and Define the error for that so we say Ena barking errors and we say error and in here we say cannot bark is sleeping all right then we say if you're if if you're asked to bark and you're sleeping then we say Throw barking hers uh cannot bark is sleeping all right otherwise we bark and then we do something similar for this actually let's see what error we're getting in here throw okay because this function is not marked with throws so let's just change that to throws and we're also going to change this function to throws okay now we're going to go ahead and create another enumeration in here and we're going to call it uh running errors I think let's just say enum running errors errors error and then we say case cannot run is injured and we do the same thing in here so let me just copy this code and put it inside run and we say if is injured okay so we cannot run if we're injured then we say running errors cannot run is injured otherwise we say running or run something like that okay so I think you get the point so you cannot bark if you're sleeping or actually not you and not me either it's the dog so the dog cannot bark if it is sleeping and it cannot run if it is injured unfortunately okay so now that we have those we will also go ahead and create another function and we say funk bark and run which combines those two functions then we say try bark and try run now what happened in here we just said try without having it do and catch what happened is that we're inside a function that can throw and if you mark your function as throws you can simply just try things you don't have to wrap them inside do and can what happens is that if any of these functions that we have inside bar can run throws then this function itself will throw so if you call this function and you call Bark then Swift goes in here and it says oh is it sleeping yes then it throws this error from this function and since that that function was invoked from this function then it will throw the error idea essentially from this function out to the caller okay so if you have a function marked that throws inside it you can try statements without having to wrap them inside doing catch in some rare cases you actually want to wrap them inside doing catch because perhaps let's say that your back-end developers tell you that hey if someone calls this function and this particular function throws an error then I want you to actually send an API request to the back end to log that error because that should never happen for instance okay so then you can say do okay try and then you say catch and in here you'll do your API okay you do your API call all right and then you can actually rethrow this error as well so and we probably will talk about that soon as well but just know that inside a throwing function you can try your statements without having to wrap them with that within do and catch okay so let's go ahead and create a little dog in here that unfortunately is both sleeping and injured so we say dog it's an instance of dog which is injured and it's also sleeping all right then we go ahead and we create a do and catch Block in here we say do and we say catch dog barking errors cannot bark and also we want to catch dog sleeping errors actually what did we have running here sorry running errors and cannot run is injured okay so you can see how we're catching both of these errors at the same time just using a comma and we'll also have a catch all in here so we say cannot uh bark is sleeping or cannot run is injured all right and in cash we say some other error and inside do we're going to say try dog dot bark and run all right so you can see now when we do that we say we get this catch statement here that says cannot bark is sleeping or cannot run is injured because we've basically caught both of these Earths in the same Clause all right you can separate them if you want to just using separate try statements now if you go and change these to false you will see that none of those errors will be thrown meaning that we will just not see anything in here basically so we can say dog just to confirm that this try statement actually ran its course and went to the next Lifeline 115 here okay let's revert them back in here so we have this example as well now now in case you're catching errors in separate catch statements just know that only the first Throne error will be caught all right so in here we caught both of them but again Swift called this block not because both these errors happened but it called this block because one at least one of these happened because remember when a function throws the execution of that function completely stops so barking throws an error Swift doesn't even go to running meaning that this uh this error will never be thrown therefore only the bark a function will throw its error which is right here Swift just completely stops the execution of this function and will run I will basically run its course out of it a step out of that function this error will be thrown and then we will come in here okay and we can actually test that let's copy this code and paste it in here and then we're going to go ahead and separate these catch statements and we go in here and we say catch first cannot bark is sleeping and when you say cannot bark as a sleeping then we will say catch dog dot uh running errors cannot run is injured and we say cannot run as injured like this and you'll see now only at the first error that was thrown will be caught which is cannot bark as a sleeping even though and this dog is both injured and is sleeping but the Run function will never be caught inside the bark and run function simply because bark through an error breaking the entire function call basically in here okay so that's how you can actually understand how you can catch verse and I hope now you know basically the flow of when errors are caught and that you shouldn't really expect to be able to catch multiple errors at the in the same do statement basically all right now let's talk about rethrows I said that we're probably going to talk about rethrows but I think it is time and now to talk about it so when we talk about rethrows we're talking about a function that internally calls another function which can also throw so let me just share an example let's create a function here called full name okay and we take in a first name which is an optional string and then we say a last name which is also an optional string and we say okay we ourselves cannot calculate the the full name we actually need a function that can't do that for us inside this function so this poor little function can't really do anything it just takes the first name and last name and calculates the full name now this ER is really stupid and I mean it is really not how you probably want to do your uh write your sift code but it is just here for the purpose of demonstration because if we didn't do a simple function like this and which looks dumb it would have to go ahead and create a very complicated function which indeed is production ready and you would probably use it in production code but this is a little bit easier at least to get into what rethrows keyword means in Swift so please just bear bear with me so we say we have a function that actually does the calculation we call it calculator it takes in a string and it takes two string optional parameters and it is a throwing function so we say it actually throws and it returns a string in return okay and then we just do this then we create our own function body in here so all these errors are going to go away now since this function is going to call this function it has to do a try right because this function throws therefore this function should also throw so then we say throws all right and also produces an optional string then okay we say try calculator and in here we have to pass the first name and last name so we say first name and last name all right so if you look at this code you will now see okay we're trying something in here okay and our function is called uh it's marked as a throws anyone looking at this function will think that somewhere inside this function we're probably throwing a specific error like we're actually um have some errors that we know what they are and we're throwing them perhaps okay however there is another syntax for this and it is called rethrows and how this really works is that it this tells Swift that this function in itself doesn't throw anything it is gonna basically invoke some other functions that throw all right so we could have gone in here inside the bark and run function and say this rethrows okay and you can see that our code will let's actually see what happened must take a throwing function argument and this is is really good we're seeing this I mean this is a example and why we actually didn't mark this as free throws so in order I mean the error is a little bit cryptic but what it is telling us really is that if for a function to be able to be marked as a rethrows it has to it has to have an argument that is a closure which throws and it should call that argument and since this bar can run function it doesn't have any argument that is a closure it doesn't even have any arguments that it cannot be marked as rethrows okay and that's what that error was telling us however this new function that we have in here has an argument that throws and we're actually calling it using try and therefore we can Mark our function as rethrows and this tells Swift that this function in itself is just calling an argument which is a closure which in itself throws on her okay so it's just a way of telling Swift that hey we have a throwing function in here and we're calling it and just we re-throw the errors that this function might eventually produce okay so let's then go ahead and create an enum in here and then we say enum oops enum and name errors and it's a it conforms to the error protocol in here and we say case first name is invalid and case last name is invalid all right then we create a function that can produce a a full name based on a first name and last name so we say func Plus it's an operator then we say first name is optional string in here then we say last name as well as an optional string and we produce a an optional string in return okay like this and we also can throw all right good and you can see we created this function with first name optional last name optional and result optional as well and throws and this function signature matches this you see optional string optional string throws at returns an optional string and the reason we created this function is simply because we want to call this function and instead of the calculator we're going to pass a reference to this plus operator in here okay so let's say we want to ensure that both um both the first name and last name are presented so we say guardlet first name so we ensure that first name is available and we say in case the first name is empty okay so the way you should read the statement is that we say make sure first name is available and make sure first name is not empty otherwise this is how I usually read my card statements okay make sure something and something otherwise which is the sales do this throw name errors first name is invalid alright so if first name is nil or that it is empty then we throw this error then we're going to do something similar like this then we say guard let last name ensure last name is present and that it is not empty otherwise say last name is invalid so you throw that error and if everything then goes fine then we say return and that first name and last name and you see these variables in here are not optional anymore and that is simply because we're doing a card let okay after gartlett is executed I mean if last name is nil then you never get here and that's why Swift knows that if you did get here and it means that you've already checked that last name was not nil therefore the data type for last name is not an optional string anymore it is actually a string same thing with first name it is string and not an optional string okay now that we have those we can go ahead and try to invoke this function right here which is full name so we go ahead and say we create a do Block in here and we say let Foo bar is try get the full name and we say first name let's say first name we say nil last name is nil and for the calculator we pass a reference to our plus operator in here okay and then we say we have to catch some errors in here so let's say catch and we say name errors first name is invalid then we say first name is invalid then we say cash also namers last name is invalid last name is invalid like that and then we will also have a catch-all block in here we say catch let err for instance and we say some other error and that is equal to err okay and you can also put parenthesis around this as well but this this is completely optional I think actually this is a little bit cleaner to read so now you can see that we're getting first name is invalid thrown in here okay and that is simply because our code just came in here I was like can I unwrap first name is there a value in it nope then it throws this error so it doesn't even go here and it doesn't it definitely doesn't go in these cases either okay so let's change this let's change the first name to Foo and you will see that your error will be the other one which is last name is invalid and then you say last name is bar then all of a sudden your function is gonna produce Foo bar for you okay so let's let's go ahead and do one more test and in here you can see that our function which is this operator is marked as throws but it is still returning an optional string however internally it never returns nil it either throws which is caught by this guy or not caught by it is covered by the sky or it actually returns a valid string so why is it marked with returning an optional string and this is actually a really good good question it doesn't necessarily have to be an optional string it is better that it is not and it still matches inside this function signature so because this is a promotion the a strain is not optional is a promotion of an optional string so it can always match it but if the emotion will never match inside a function signature okay so you can if if this requires a string you can never use a function that returns an optional string you will actually get an error now or we should get an error there we go okay so just remember a promotion will work but a demotion won't and this is a promotion we're saying that although you need an optional string which is at a lower level meaning that it can be nil but we will always produce a string which is at a higher level meaning it's never optional so it is a promotion a promotion function signatures in Swift always works okay good we've now talk about that now let's also talk about results and results are also very important to understand they're kind of related to error handling so that's why I wanted to name them and they're usually useful when you're writing API calls okay so what we want to achieve in here is to create a function that is called get previous positive integer and you will pass an integer to this function and the res and the responsibility of this function we're going to develop is to find the positive integer right before the integer that you pass to it as an argument so if you pass two this function is going to have to return the value of one if you pass one this function has to return zero but what happens if you pass zero there is no more positive integer before zero because the next number if you do a minus one to Z basically say zero minus one you are going to end up with minus one and that's not a positive integer so you could say well let's just throw an error and you'd be right you could just Mark your function as throws but there is another way of doing that there is another way of saying that a function fails but it fails perhaps a little bit more gracefully it doesn't actually throw an error but it carries an error with it okay and this concept is also available in many other programming languages you have it in Dart you have it in Python you have it in Rust so many other programming languages have this concept and in some languages it is called either but in Rust sorry in Swift it is called results so let's first go ahead and Define our error so we say enum integer integer errors it is an error and then we say case no positive integer before this value okay enum error case did I do something incorrectly in here it doesn't look like it formatted it right but this is fine okay then we create our function we say func and we say get previous V is positive integer and we say from int all right and in here what we need to do we are not going to say that this function throws but instead we're going to say that this returns a result that is either an integer or an integer error like in here okay so now all of a sudden instead of this function just saying I throw anything you're saying it either gives you the result or it gives you an error of this specific type which is a little bit cleaner to be honest with you because a throwing function doesn't necessarily specify or it can't really specify the type of errors that it throws so the color the call side to that function always has to have a catch-all block in order to understand okay what error is actually being thrown by this function but by using a result you specifically say which Earth you're gonna throw not really throw but which Earth you're going to carry with you if any all right so let's guard that this integer is more than zero otherwise we say return a result that is a failure and its failure is indeed an integer error you can see in here that is no positive integer before this value and the value is this integer right here okay so regarding that the ins is more than uh zero basically because otherwise we can't minus one all right then after this we say okay in that case we wanna in any other case where the integer is more than zero then we have to return a successful result and we say return a result with success and the value is integer minus one all right so you see how this function is structured at the moment okay then we go ahead and create a create another function which internally calls this function so we call it funk perform get and this is just to add another layer of complexity really to our code so that we don't go ahead and directly call this function I just want to show you how you can call this function within another function okay so we say perform a get for a value and we say value as an INT and inside this function we're going to call the other one get previous value sorry get previous positive integer from value and then since this guy returns a result and if you look at results you can see just like optional result is an enumeration meaning that you can switch on it so let's switch on this guy and we say in case if we get a success and we say previous value all right uh actually success previous value maybe not previous value previous positive yet previous value then we say previous value is previous value but in case we get an error we say case failure and we say error then you can say okay but this error it is in itself an enum it is an integer errors enum we already know that so since it's an enum you can have another switch within your switch the first switch is switching on this result and since it gets the error which is of type integer errors with it itself is an enum then you can have another switch in here then you say switch error in the case of no positive integer you put a let in here and you say this value then they say no positive integer before this value all right so now that we have this extra logic in here we can go ahead and call our perform gets function so I'm just going to copy paste some code in here you can see first we pass 0 to this function and let me comment this line out we first we pass 0 and 0 then count so that zero comes in here and it's then passed into this function then it comes in here and says make sure int is more than zero oops it's not return the failure and then it comes in here into failure gets the error we switch the error is it no positive integer before yes it is indeed and then you get this line printed to the console no positive integer before zero and that's correct okay then we bring this go code back you can see now it will hit this block and it says previous value is one all right because the previous value before 2 is indeed one so that's short and sweet about error handling in so if you can either use throwing functions and throwing Constructors for instance and then do and catch and you also looked at try with a question mark which optionally tries a function or try with an exclamation mark we should try to always avoid actually because it can crash your application and then at the end we looked at how result also works in Swift and how it it goes hand in hand with error handling in Swift as well okay now that we're done with error handling in Swift let's talk about Collections and collections is something we've talked about up to this point a good maybe five or ten times and the five to ten times I would say but we haven't really gone into details about them so I'm gonna close this playground in here I'm going to press command n and say blank in here and let's create a new playground and we're going to call it collections all right and ensure that it's created in your main workspace and then we say create and just like normal we say import foundation and run this playground also automatically we get rid of our Explorer here and then we can start talking about collections so collections as their name indicates there are a collection of stuff all right so for instance with numbers and if you're I mean not if but since you're already familiar with other programming languages collections are also called arrays or dictionaries or even Json objects for instance if you're working with simple JavaScript you can just say const something is equal to and then you add your values in here value blah okay so this is a simple Json JavaScript and it's some sort of a collection and in Swift you also have different types of collections one of them is an array so you say let's numbers is one two three four for instance and then you can do different things with this collection you can say give me the first value give me the last value give me the count of objects in here or you can say numbers map every element to its minus counterpart so you can see in here then let me just bring this over so you can see we have one key one two three four then the first element is one last one is four there are four elements total and then here we mapped every element inside this numbers array to its minus counterpart okay so this is an operator in here now if you have an array in Swift you can also mutate it as long as it is a variable so let's say VAR mutating numbers and we say 0 1 and 2 and then you can see mutating numbers append the value of three and then mutating numbers insert the value of -1 at the index of zero okay so index of zero is right here not that the zero is actually let's let's just say four five and six instead okay and then we append the value of seven and we then insert the value of three at the index of zero meaning that the array was four five six but at the end it will be three four five six seven you see what happened in here the index of zero is right here and in the index of one is right here index of two is right here because the in index is in arrays and any collection in pretty much every program language that I know about they start at the index of zero they're called zero based indexes okay so and apart from doing a pens and inserts you can also insert a whole array inside an array so you can say mutating numbers insert and then you can say insert the contents of for instance one and two at the index of zero so let's see what happens in here and then right it's not insert it is actually insert contents off so this API calls called insert contents off and you can see the resulting array will be one two three four five six and seven here okay you can enumerate over the elements inside an array by just using a for statement for Value in numbers so then you can say a value and print it to the console and now um playgrounds have an interesting way of showing values over time since we're animating over these values and there are four of them it can't print them all in the same line so you have to click here I believe and it gives you like a little graph and then you have to right click on it and you say value history then you get the values one two three four otherwise it shows you a graph for some reason okay and let's somehow remove this okay there we go so that's how you would go through values inside an array okay you can also enumerate through items inside an array with pattern matching using the where Clause so if you want to for instance grab all the uh all the even numbers inside this array so because you saw this printed one two three and four and one and three are not even numbers but if you want to grab only the even numbers you could say four value in numbers where value and we're basically the the result of dividing the value by 2 should be equal to zero okay so this is how you would do your pattern matching if you say value in here we can do the same thing that we did earlier and say value history and then you only get the values of 2 and 4 in here okay so that's how you can have a where Clause right after your four statements now you can also map objects inside an array and mapping is also very important because it's one of the most useful functionalities of collections mapping means that you take the values inside that collection and you turn them into something completely different if you want to okay so let's say numbers you map them you see and it says okay I give you the number so let's say value and in here you can say I return anything in this case we've decided to return an integer and we say value multiplied by two now you can all of a sudden see that numbers are 2 4 6 and 8 whereas they were originally one two three and four so here you multiply them by by two however inside map you can't return anything you can say I actually return a stream okay and then you turn these into a string you can string first multiply them by two but then turn them into a string now you can see there are strings so map allows you to map it to anything all right and now that we're talking about mapping it to anything you can you can guess that this map is indeed a generic function because it allows you to change the resolved value and if you look at its signature you can see it in is it indeed giving you the elements inside the array but it allows you to throw to return anything and the result would be the array of that anything okay so if I go and say let values you can see values is an array of um not in this case but in this case values will be an array of string okay like this so values is an array of string right now and just a note about this at Maps don't necessarily have to be this complicated I mean um to me this and actually we can recommend this syntax more than I can recommend the next syntax I'm going to show you and simply because the more information you give to the Swift compiler the faster your code compiles in larger applications but if you have very simple applications you don't have to do this much syntax work in Swift you could literally just say okay first of all I don't want to give you I don't want to tell you what return value I have and Swift still is happy with that you can also remove this in here because Swift already knows the value is an integer okay and this works as well and you can completely remove that and instead of value use dollar zero and that works as well so your code could pretty much just look like this but again I mean this does work but it is it has a very little information about what that code is actually doing internally so so a new newbie software developer may be quite confused by it and also as I said this is more information to the compiler which allows it to compile your complicated codes in the future a little bit faster as well okay apart from mapping arrays you can also filter them meaning that you want to grab specific values out of this array you could say numbers then you filter and you say you get the value and you turn and return a Boolean and for all the objects that have to be included in the result of this filter function so you say if the value is greater than or equal to 3 then it should be returned from the result and you can see the result is 3 and 4. okay so that's how Filter Works you can also do compact mapping and compact mapping mapping is similar to map but it returns an optional and the values that are returned from this compact map which are nil will not be included in the results so it's a compact map is a combination of map and filter okay so let's have a look at that we say numbers compact map and we say we get the value as an integer and we return a string okay an optional string remember it should be optional optionality indicates a filtering so if it is nil it won't be included in the resulting array then we say if Val value is divisible by 2. then return the string of that value otherwise return nil so let's break it down into separate lines it's a little bit more readable okay so you can now see the result is at Raf strings that only includes two and four but it doesn't include three and one or one and three basically okay so compact map when you see it just know that is a is a combination of map and filter at the same times arrays in Swift can also contain the value of nil so let's say numbers uh numbers numbers two and it is an array of optional integers so meaning that it can contain not just integers but also nil then you can say one two and then nil four and five so this is completely fine all right and then if you say numbers two dot count you will actually see it is five because nil is one of the elements one of the valid elements inside this array and if you want to grab all the values inside this numbers array and that are not nil then you would say let's not snails is equal to numbers 2 filter so you basically say here's my integer and I return a Boolean for all the values that are not known then you could say um let's say its value its name is value then we say value shouldn't be nil like this all right and you can see the result of this is just one two four five all right however however this you will be like okay we've checked that the values are not nil and we place them inside this array so this array should now be an array of integers but that's not correct because if you look at this is is still an array of optional integers so what's happening here is that though we checked for nail values but we didn't tell and this so basically filter doesn't allow you to change the data type all right you can see it always returns the same array of the same element type so if our elements is optional integer the result of this function will indeed be integers as well in order to grab the non-null or not nil values out of this array and also change the data type you have to use compact map all right so um so you could say in here not Nails is numbers too and we say compact map and we say we take the integer and which is value and we actually return an optional integer as well and just return the same value all right if this value is nil it won't be included in the result and also it won't basically change the data type so not Nils is now not an array of optional integers okay I know it's complicated and it's a lot of generic code but it really requires that you work with these functions yourself to for it to basically click now arrays can also include instances of the same object multiple times so if you say numbers three and we say one two one two you can see that numbers three dot count is indeed four so it contains four objects it doesn't check whether there are unique or not okay arrays can also they don't necessarily have to include home homogeneous objects so they can be heterogeneous meaning that you can have integers and strings uh mixed up and Blended up in the same array so let's say let's stuff one and we say it is an array of it has an integer of one then it has hello then it has an integer of two and has a string up world but this will give us an error or it should because it says it is not a homogeneous array all right and it says it's a heterogeneous so in order to fix this you can see Swift is telling you to actually add as any to the end of this array and a collection literally could only be what is the same as an array of any and I mean this to me looks fine uh but I'm sure I'm not sure really what is the same collation level It could only be inferred to any add explicit type annotation um I believe we've already done that so I'm not really sure what it is complaining about let's just say stuff one and see if Swift has understood what this code is actually doing expected separator did I miss a separator somewhere let's stuff one to me this looks fine but not sure really what it is complaining about let me just bring it in here and then we say hello let's put all of these in oh because I've missed a comma in here I can see okay sorry about that so I've missed a comment there so now you can see our array looks fine and if I say stuff one count it should include the count of four in here okay there are four objects so this is a trick to get your array to include heterogeneous objects as well all right so um we can also go ahead and change the Syntax for this so if I copy this and paste it in here and changes the stuff too and then stuff to account if you don't want to have this as in here you can also tell Swift that this is in fact an array of any by doing this column in here just specifying the data type right there okay so that's another way of actually achieving the same result now that we've talked enough about arrays let's talk about uh sets a set is a special object it's a special collection that only contains unique values all right and the way it calculates uh uniqueness is based on hash values and equality all right and this is a little bit complicated a lot of people think it's just hash value but it is not it's also equality which is very important to understand and what sets so let's create a set we say unique numbers and then we say it is a set of the values one two one two and three all right and then we say unique numbers count and then unique numbers map them to their minus values let's just see what values we get in here you see after the creation of this set the set only includes the values of three one and two so two things are quite interesting about this is that it removed the duplicates so both twos were not included only one instance was included it and the same thing with the value of one only one instance was included so that's one thing that's interesting about creation of this set or and one of the properties that's important about sets it only includes unique numbers and the other one is that this array that we just passed to it it's ordering was completely changed within the set so sets in Swift cannot guarantee ordering as you pass the ordering to it so the ordering could just be mishmashed and the set will order the items as it pleases all right so sets can also contain Nils so we can go ahead in here just like arrays so let's say my numbers is a set of one two three and nil and five and then we say let's not nil numbers if we want to get the not nil numbers then we say it is a set of my numbers and then we compact map this guy a compact map and we grab only the current value you can see in here compact mapping let's actually break it down into separate lines so it is more readable like this and like this all right so we're just taking the same values which are inside my numbers returning returning them from compact map compact map what it does is if the values are nailed it removes them from their result and you can see the result of compact map inside a set it is an array of the values and that is the reason we're putting it inside another set because we want the return value to be a set as well all right and then we say not nil numbers in here you can see in here we have five where is it uh two three nil one five but in in there we have only three two one and five so nil was removed essentially by calling compact map on that sets okay now you can also create heterogeneous sets just like you can create heterogeneous arrays so a set doesn't necessarily have to only have integers for instance so the trick to do that is to create a set of a protocol called any hashable all right so you say stuff three for instance and we say this is a set of any hashable and you can look at the code for any hash well sorry it's not a protocol it's a structure and we say it is equal to uh one two three and then bounded all right then we can say stuff three count you will see that includes four values all right so this is the trick to create a heterogeneous sets as well now if you want to extract specific items uh like of specific types out of uh any of these sets or arrays and let's just focus on the sets right now actually let's have a look at our stuff one you can see our stuff one is an array at the moment and that is an array of any but if you want to grab specific objects out of this array which are of specific types for instance only the strings or only the integers you can use a keyword which is called as so let's say let's ins in stuff one and again remember stuff one is this array it has integers and strings and you only want to grab the integers out of them so then you could say ins in stuff one is stuff one and then you compact map all right remember compact map does map and filter at the same time then you get your value which is any and you want to optionally return an integer then you say value as ins so you compare the values type to an integer and optionally return it if it is integer okay and then you can see in here that the result of this is only your integers and you can do the same thing with strings so you can say okay let's copy this and then we say strings in stuff one and then you get the value and you optionally return a string and then you say as long as the data type is a string I return it okay then you get the hello world printed in here okay so if you if you are comfortable doing this with a race then you're probably also comfortable doing that with sets and it is very similar it's actually compact map on sets as well so let's copy this code ins in stuff one and then we say ins in stuff three and remember stuff three is a set then we go in here and we say stuff three and we compact map and the value is any hashable hashable and then we optionally return an INT and then we get the result printed to the screen which is two three one and you can see one two three van dot so van dot was essentially removed from this set but one thing to note about this is that as I mentioned before compact mapping on a set doesn't return a set it actually returns an array so if you go in here and call type of which is an internal function in Swift and say give me the type of ins in stuff three it will tell you that this hopefully is did it crash it will tell you it's an array it's not a set anymore though stuff 3 was a set uh you can see in here is a set but the result of compact mapping is set is an array okay so just keep that in mind now now that we talked about sets a little bit and we talked about that they can contain the only that they only contain uh unique objects then the question is how does it calculate uniqueness and and the way it does it is using a protocol called hashable now hashable a lot of people think that only thing it does it it contains a some sort of a hash value is some sort of an integer value that uniquely identifies every object but it but hashable protocol in itself also includes equality all right so uh without without actually me talking too much about that let's have a look at an example so let's just say we create a person struct in here struck person and then we say we have an ID so every person has an identifier we have a name of string and then we have an H of integer as well okay and then we want this person to be able to instances of this person to be able to be included inside sets Okay so without making and without making this person hashable let me show you what will happen if it is not hashable and you try to create a set out of it so let's say that we have a foo ID in here and we say it is a uuid then we say let Foo is a person with the ID of Foo ID its name is Foo and its age is 20. all right then we create a bar person in here and we say bar is pretty much similar to Foo and we say bar but we forget to change the ID and bar is also using the foo ID its name is bar and its age is 30. all right now we want to go ahead and create a set of Foo and bar so let's say we have people and we say it is a set of person and it is equal to Foo mbar now we should get an error ideally from Swift telling us that these objects are not hashable you can see it says it does not conform to protocol hashable all right so how do we do that how do we ensure that they conform to hashable so let's go ahead and say that they conform to Hash Rule and everything will just go fine nothing will happen in here you won't get any errors okay and if you go in here and say people that count let's go in here okay you will see unfortunately it is still two so what happening here we said that well we are making this person hashable and it should ideally not be placed twice in this set because uh it is pretty much the same but if you look I mean same data but what happens in here is two things when you when you create a structure and you just say it is hashable without having any custom logic in it meaning that you didn't actually tell Swift how to calculate the uniqueness of this object what Swift does is that it looks at all the properties of that object and says okay are all these properties unique themselves like are they hashable and if you look at uuid is indeed hashable if you look at string it is hashable uh let's see extension string hashable somewhere it should have been made hashable I'm not sure if it is exactly there we go extension string hashable and also if you look at the code for INT it should also be extension and hashable there we go so since all these three are hashable then Swift says okay I'm gonna calculate the hash value myself then it says okay you created a person it has the ID let's just say it's hash value is one let's say then it says oh the name is Foo the hash value is for instance 10. I'm just making this up okay and the hash value for this guy let's say is 20. all right then it comes to bar and says oh it has the same ID as the other ones which is has a hash value of one but it's its name is bar so its hash value is let's just say 30. and the age is also 30 with a hash value of 40 for instance okay so it says okay then you put both of these inside a set and I'm gonna calculate these hashes 20 plus 10 plus one for instance okay this is not how hashes are actually calculated but we're just going to plus them together so 20 10 and 1 are going to be 31 and then we have 40 30 and one which is going to be 70 a month so at 31 and 71 are not the same meaning that they're basically not the same object and should both be placed inside the sets Okay so that's how hashing basically Works within Swift okay but what we may want to do is to tell Swift that hey we actually don't want people with the same ID to be recognized as different people so what we want to tell Swift is that if two people have the same ID then they're essentially the same person okay and in order to give Swift more information about how it should do our hashing we should go ahead and basically implement the hash functionality somehow ourselves or at least inject our own logic within it so let's create a person two object in here so a person to structure so now that we've seen that example let's say a struct person two okay and we're gonna grab let's actually grab this struct from here but instead we're just going to call it person two so person two in here and we said that it is hashable now if you make an object hashable you also have the ability to override a function in here and not really override but also Implement actually a function called hash into all right and this function comes in here because we have we've conformed to the hashable protocol all right then in here what you can do is to say hasher and then you combine you call the combine function on it and then you basically hash the fields that you want to be taken into account while Swift does its hashing so what this really did in here is that it jumped over hashing name and age and instead only hashed ID within the hashing mechanism of Swift all right so now that you've done that you also need to tell Swift whether two objects are Equitable because you've just implemented your own hashing functionality and when you say something is hashable by default it's also Equitable and what happens in here is that right now you set that take ID only into hashing mechanism but in terms of equation because hashing is also doing equality Swift if you don't intervene Swift goes and it says okay the hash values are the same but these two objects are not really equal because by default Swift is going to also equate all three properties so in here what we're going to do is to say static func equality so we're going to overwrite equality as well on the left hand side we say self and the right hand side itself then we say Boolean and we say as long as the left hand side's ID is equal to the right hand size ID then these two objects are equal so not only have we changed the way a hashing works but we also need to change the way equality Works otherwise they won't really come to an agreement with each other okay now that we have that let's go ahead and create a baz ID in here and we say it's a uuid all right and then we say we create a baz person in here which is person two remember create an object of type person two not person then we say baz ID its name is bass and then we say it has or he has the age of 20 or she has the age of 20. then we create a Cox value in here and we say q u x and we say person two and then we say baz ID and the name is Cox and the age is 30. all right so you can see now the ID is the same but all the other values are different however the way we've done our hashing and equality is that we only take into account the ID so even if their names are different but they're using the same ID then we consider them to be the same person and that's why you can go in here it's say if that's equal to Cox they are equal so this basically is invoking our equality and you can see it comes in here okay but that's not the point that's not what we're trying to do in here we actually want to add them to a set so let's say let lets people people to and we create a set of bars and Cox in here and if you look at the values inside people too it should just be one value people too that count all right simply because our hashing intervene in here and both these objects were considered to be the same object all right and if you take the first item out of this you can get a person person two and then you can say the first objects uh name give us the name all right and you can see it is pass all right so a Cox was not inserted into our set simply because baz was already there and Cox was considered to be the same object therefore it was not inserted into the set all right so that's how you can go ahead and Implement your own hashing value or hash value and equality all right that's enough about sets let's talk now about dictionaries now dictionaries they're also called Json objects and many other programming languages like like as such as um not really Json objects yeah well kind of Json objects yeah there there are keys and values basically okay and you define them using a square bracket in um in Swift so you say user info and you can create your dictionary and then you say keys are in this case string for instance with a column and you separate the keys from the values using a column and you can say the key is name the value is Foo this key is H and oops if we can spell H and its value is 20 then you can say I have an address field in here whose value is indeed another dictionary and you can say the address has a line one and it is address line one then we have a postcode for instance it's key as postcode and its value is one two three four five let's say all right and this is completely valid a swift object if I haven't messed anything up let's see Foo age address all right and we also have to tell Swift that you can see it is a heterogeneous values because some values are strings and some values are integers then we have to tell if there is a dictionary with keys equal to string and values of any type all right without that it won't work however if you didn't have this age in here and we didn't have this address in here we could have just gone away by defining our dictionary like this as Swift would have understood the data type to be of key strings and values of strings as well but since we have keys of string and value of integer and a key of string and a value of a dictionary then we have to tell Swift that the keys are string and values could be anything basically now you can grab values out of your dictionaries using type using subscripting so you say user info grab the name and you can see it will give you the value of Foo in here you can say give me the age user info give me the H so you're basically giving it the keys and you're extracting the values for those keys now you can say user info and then give me the address let's go in here address at rest all right and since this is an address dictionary coming back from here you may be hoping that okay since this is an entire dictionary maybe I can type a key in here as well and get the postcode all right and if you do this then you get an error because you've told Swift that the values that come out of this uh dictionary are of type any meaning that Swift Just believes that this is any and now you're trying to tell Swift that this is not any and it's in fact a dictionary and it should go into that dictionary and x and extract a value with a specific key and Swift Just rejects that okay there's a dangerous way of doing that forcing Swift to believe that this in itself is a dictionary and that is using the as syntax but please don't ever do this in production applications and there there are better ways of doing this so I just want to show you how it works you can say get the address and force cast it to a dictionary of type string and string you can see it because this has keys of string and values of type string as well okay so after doing that uh then you can go ahead and say give me the postcode on it all right and this should this should work but in production applications really is not a good idea to do this so let's see what happened actually found nil one on wrapping optional value and I think it's because I I misspelled address basically so it works but you should never do this because this will crash your application should this key Either not exist or that its value shouldn't be of type string or string your application will crash so please don't do this I'm just showing you so that you know this syntax also exists okay if you want to extract the keys and values out of a dictionary you can say user info dot keys and also you can say userinfo.values and this will give these this will give you the keys only you can see in here let's go in here the keys are age address name and the values are 20. let's go here 20. Foo uh which is let's see where it is it is 20. Foo and then this dictionary so you grab basically only the keys or only the values out of your dictionary using that syntax however it is more common that instead of just saying keys and values you want to enumerate over the keys and values and their Associated values you can because you can see in here we're only saying keys and only values but what if you want to grab every key and its Associated value the Syntax for it is for key and value in user info then you can print them out key and value like this okay let's see if the playground can help us extract these values so and the key says name value history you can see age address and name are the keys and the values we can also perhaps get their history let's see value it's oh the playground isn't so smart in being able to print the value so let's instead print the values and see if we can get them in the console uh like this so here are the values basically okay and you can also print the keys as well so let's say we print the keys and we print the value so uh the key of address has this value the key of name has this full value and the key of H has the value of 20. all right so we can do that as well let's just revert them back to how they work okay now you can also have a where clause in your enumeration over keys and values so let's say four key and value in user info where the value is an integer okay and then you can say key and value so you see the only value that was an integer had the key of H and it the value was of course the value of 20. all right now you can also have multiple word Clauses so you're not limited to only one where Clause so you can say four key and value and use for info were the value is an INT and a key that counts so the key is a string and we're saying it should contain only two uh more than two characters then we say give us the key and the value all right so the count is pretty much the length of the of the key and then you can see that we got the same result because age is three letters long and are conditions that it should be more than two but if in here we said more than three then this will never be cost so we won't get any results in here okay so I think that's actually quite enough right now about collections we talked about arrays we talked about sets and we talked about also dictionaries and some new formats and pattern matchings that you can do with these collections they're very very useful and I think you need to really get and get quite handy with these objects yourselves and in order to get a good grasp of how they work I can just sit here and explain these for ages but without practice and probably it will never really click so my advice is to go ahead and create some sets arrays and dictionaries yourselves to get a good grasp of how they work now that we talked about collections it is good time that we start talking about equality and hashing as well I mean we did touch upon this topic a little bit right now but we haven't fully covered them equality and hashing they're like their own whole world of understanding how they truly work and basically understanding them is the key to understanding how sets for instance work and how equation generally in Swift works and so I think it's very important that we dedicate it's um a whole section just to equality and hashing so and that's what we're gonna do right now so I'll see you there let's then go ahead and create a separate playground for this so we say um blank and foreground sorry playground and we say equality and hashing like this and ensure that you're creating it in The Roots folder like this and then we just say create and we import Foundation and we can get rid of the Explorer to the left hand side now equality in Swift is provided using a protocol called e-codable any object that conforms to the equilible protocol has to have a function a static function and which is an equality function like this is pretty much an operator and this function has to have two arguments one at left hand side and right hand side both of the same exact type as the current structural class implementing it now if you go ahead and create a person structure in here and say that this person is conforming to the equatable protocol and you say let's ID is a string and then you say let's name is a string then we create two instances of this we say let's Foo one is a person with the ID of one all right and then we say name here is Foo then we create food too right here and we say the name is actually bar then if you say if Fu one Foo one is equal to Food 2 then we say they are equal with an exclamation mark in here because they shouldn't be they are not equal otherwise okay so what happens in here is that by ensuring that this person is Equitable all right let's also make sure that this is running automatically by conforming the struct a person to Equitable as Swift goes in through all the properties of the structure and ensures that they are indeed themselves Equitable string by default conforms to the Equitable protocol and so does this one so then Swift says okay then I understand that it should be Equitable however if you go in here and say a struck dog and don't make it Equitable and in hear you say this person should also have a dog all of a sudden Swift will throw an error in here saying that oh I can't give you equal Equitable by default because dog which is one of the properties of this person's structure does not conform to Equitable if you want to get rid of this just ensure that this dog is also Equitable which then gets rid of the problem in here but the only problem we have in here that is that we need to pass a dog instance in here but we're gonna remove all this dog reference in here just wanted to show you how default implementation of Equitable basically works it looks at all the properties and then make sure that they're Equitable and then goes through all of them one by one compares the properties between these two objects that we're comparing okay now you can also override equality and uh you can basically say let's say that you in your person uh structure you want to say any two persons that have the same identifier should be considered equal so then you can say extension person and you can see at the moment these two objects right now before our extension they're marked as not equal all right simply because their names are not equal but if you go to extension person and then Define the static function equal equal like this and you say left hand side itself like this and right hand side itself as well and this function should return a Boolean indicating whether the two objects are equal or not then we say if the left hand side's ID is equal to right hand size ID then these two should be considered equal now all of a sudden you see that this will be flipped to they are equal previously before this extension this branch of code was being executed because by default there were not equal since they had different names however with our extension in place since we're only comparing the IDS then they're marked as equal so if you comment your code out you can see all of a sudden that this Branch will stop being executed and instead this Branch will get executed all right so that's how you can create your own equality on custom objects so we can comment this guy out apart from structures you can also Implement custom equality on enumerations let's say that we have an enum in here we call animal type and we have a case where a dog and we ask for the breed and also we have a cat and we ask for the breed okay now let's say that you want to compare these um to with each other if you go ahead and say let's dog and say is an animal with a type of dog with its breed is a labradoodle and then you say let's whiskers is an animal type another dog basically exactly of the same type then if you go ahead and say if dog equal to whiskers let's just change this to maybe dog two dog one and Dot two and then we say if dog one equal to dog two like this you can see that you get an air from Swift because by default animal type is not Equitable you can go ahead in here and say okay well I'll make it Equitable does this work you'll be surprised to see that actually my default what Swift does is it looks at these values and says let me let's put some values in here and say they are equal like this otherwise we say else they are not equal all right so since dogmon and dog 2 we actually are giving them the same values in here then suit by default says oh they're equal but if you change the value inside this breed for instance then Swift says they're not equal so Swift does the same thing that it does with structures as it does with enums it goes through all the properties of those enum cases and then make sure that they're Equitable if they are it will just call the equation function on those parameters as well and Compares them with each other if all those they're equal to each other and the case is equal to the other case as well then the enum cases are marked as equal however you can go ahead and change this implementation so you can say extension extension animal type and let's just remove the Equitable from here and we say animal type becomes Equitable in this extension all right and then we go ahead and Implement a an extension and sorry the static Funk left hand side itself and right hand side itself as well and then in here we say bull all right so now what we want to do in here is to compare the breeds with each other so we say we switch the left hand side and the right hand side then we say in case and we have a dog with the left hand side breed and another dog with their right hand side breed then they're considered equal as long as the left hand side breed is equal to right hand side breed we do the same thing for cats so we say if we get a cat in here and a cat in here then they're equal to each other as long as their breeds are equal and since this pattern matching is the exact same thing between dog and cat you can see they're getting left hand side breed right hand side Bree and the same thing in here you can remove this coating here and just put a comma and remove this case as well all right so they're basically doing the same thing and then you can go ahead and say anything else they're considered not equal to each other okay so as long as it's a dog and a dog and their breeds are the same then it's considered to be the same and if it's a cat and a cat then they're considered to be the same as well so let's see what we got and we got this oh we have to return this of course we can't just write that statement in the playground good then we can go ahead and um basically we've now created an animal type let's go ahead and create an animal now so we say it's struct and we say animal animal in here animal and we said let's name is a strain and then we say let's type is an animal type okay and since both string and animal type by this point are Equitable you can make this animal also conform to Equitable all right however what we want to do is to say okay the animal equality has to only look at the animal type we don't want it to look at the animal name that is the default behavior that Swift looks at all the properties but in this case we just want to look at the animal type all right so let's say that then we override the static oops static Funk equal equal and we say left hand side itself and right hand side itself as well and we return a Boolean okay and we only look at the types so we say left hand side type should be equal to right hand side type otherwise they're not equal okay then we can go ahead and say let cat one is an animal and its name is whiskers like this all right and it's animal type is actually a cat then we say it is a cat of type Street gap of the breed Street cow okay let's put that in here and this is also a shorthand of writing um the animal types instead of saying animal type in here you can just say dot cat so instead of doing this you can just do the shorthand and so it will understand the code anyways let's copy this code and then we say cats number two and its name is whoosh okay just like that and it's also a straight cap so looking at our equality functionality in here we only look at Types on animal in order to to determine if they're equal to each other or not so then we should be able to go and say if cat1 is equal to cat2 they are equal because of their breed actually type because of their type else and they are not equal all right and you can see that this branch of the code is being executed simply because our equality custom equality on animal only compares the animal types and since they have the exact same type of cat and Street cat then our code works and you you can actually go and remove this implementation on animal type because this pretty much is the same thing that Swift provides Equitable and you can see the code will be executed just like before so no difference really so it's up to you if you want to do custom implementation of Equitable or you want to let Swift deduce this on its own if Swift can already deduce this on its own which it can you shouldn't really go and write an exact same implementation so this this is pretty much just redundant but if your custom implementation of Equitable adds some functionality to how swift does it by default then please go ahead and add your own Equitable to your custom types okay so we can now we've had a look at Equitable let's look add a hashable and we've already talked about this a little bit before but let's just talk a little bit more in details about it just like Equitable hashable also looks at all properties of a struct or a class to make that start or class hashable so if you say struct house and we make it hashable then we say let's number is int and we say let number of bedrooms is an INT then we say let house one is house with the number of one two three and number of bedrooms is let's say two all right and then we say house one and you can see now you have a property in here called hash value and that is coming from the hashable protocol in here then we go ahead and create another house we call it house number two in here okay house two and its number is one two three but it's number of bedrooms is three and then we print out its hash value in here as well now you can see these hash values are different simply means that they basically if you create a set with house one and house two they can occupy their own space and not overwrite each other however if you go in here and say number of bedroom and bedrooms is two then you should ideally in here see the exact same hash value meaning that you cannot put both houses inside the same set and expect them both to basically appear in the set one is going to overwrite the other one okay so if we go ahead and create a setting here we say let houses is a set of house one and house two and please note that I changed this back so it's now number of bedrooms two and this one is three then if we say houses dot count then you can see we get two in here because none is overwriting the other one let's see if the playground is going to be able to update soon hopefully even if it doesn't show the count we can still see in here that we have one house in here and another one here and now the count is also being displayed right there okay really good you can overwrite the uh how hashing of course Works we've already had a look at this and when we talk about collections but let's have a look at another example so we say a struct numbered house okay and we say it is hashable like this and we say let's number is int and then we say let's number of uh bedrooms is an end and this is pretty much the copy of the house structure but we had to give it another name and because you can't have two structures with the same name in the same code scope in Swift okay then in here we're going to go and overwrite this a hashing mechanism so we say hash into and we say we only want to combine the number into the hasher so we say combine the number and this simply means that as long as two houses have the same number then they're at the same house pretty much when it comes to their hash values okay however this doesn't mean that they're equal you have to override equality as well so say static Funk equal and we say on the left hand side we get self and the right hand side we get cell self as well then we say this returns a Boolean and then we say as long as the numbers so we say left hand side number is should be equal to right hand sign number and then both houses are considered to be equal to each other in that case Okay so let's create let house three and please make sure you create a numbered housing here not a house it's house number we say one two three and number of bedrooms is two okay so as a house number one two three then we create another house we call it house four in here okay like that and then we say it is a numbered house and the exact same number as this house however it has three bedrooms okay then we create a set of these we say houses at three and four it is a set of house three and house four and then if you look at houses three and four count you can see there's only one object inside this set simply because house three and four they can only consume the same space in our sets and simply because their hash value is the same you can see in here and let's see if playground is going to be able to update our codes hopefully soon if I close this one maybe it's just gone crazy a little bit let's say automatically run hopefully it can run the code so you can see there's only one value in here and if you say houses three and four get the first item then it gives us a numbered house and then we can say get its house number bedrooms and it says the number of bedrooms is two and the reason behind this is that house Ford could not be placed in the set simply because there was a house already in the set with the same hash value and you can also look at the house at three hash value and house for hash values and they should pretty much be the same simply because the hashing algorithm is only taking the house number into account so you can say house three house three number dot hash value and it should pretty much be unique as well and you can see they're exactly the same thing okay and house for that number hash value there the same as the entire hash value of the house okay another example now EMS are by default hashable even without raw values so I'll show you in here we say enum car part car parts like this and we say case a roof uh case tire and case trunk then in here we say let's unique Parts is a set of car parts okay and it's equal to a set that contains a roof it contains Tire it contains another roof and then a trunk so since this is a set of car parts and it doesn't have any raw values like we're not doing it like this so they don't have raw values if you in here say unique part oh actually we can see the value already here you can see it only contains trunk roof and tire so it doesn't contain two roofs that's what I'm trying to get to so if you create a simple enum in Swift without any raw values or any Associated values it's by default hashable and Equitable all right that is the whole point now if you have an enum with um with Associated values then you can basically go ahead and change the hashing mechanism yourself so let's say that we have an enum in here we call it house type and it has a big house and we say its Associated value is a numbered house and we say case small house it is a numbered house like this and then you can go ahead in here and say this is hashable all right so as you do that Swift looks at the properties that are inside this enum and it understands that oh this big house is of course hashable because it's an inum case however it has an Associated value then it looks at the associated value and says is this value hashable then it goes to numbered house and it says yep it is hashable then it implements hashable by default for you on this house type okay so then you can go ahead and basically add these into some sort of a set so let's go ahead and we say we create two big houses we say big house number one is a house type big house like this and it has a numbered house inside it like this all right and this number it has has a few properties it has a number and we say number one and it is number of bedrooms is one as well so we have a big house and that's number one in that street for instance and it has one bedroom for some reason a big house with one bedroom only then we say a big house number two in here okay let's get rid of this Bottom bar then we say it is also a big house at number one and total number of bedrooms is one on that one as well then we create a small house so we say small house one and like this small house one it is a small house house and we say it is at number one as well and it's number of bedrooms is one all right so now we have three houses with the same number and two of them are actually the same house type as well so what's going to happen if we go and put these inside a set so we say all houses is a set of house type and is equal to a set with a big house big house one big house two and small house one all right so if you say all houses the count in here then let's see if the playground can resolve this you can see there's only two objects in here the reason is that big house one and Big House 2 are considered to have the same hash value simply because that their numbered houses have the same hash value and their cases have the same hash value however small house one is of type small house not big house though it's numbered house has the same hash value as the other numbered houses however the enum case itself also has a hash hash value therefore in here you can see if I say all houses first and all houses actually let's see if you can get the values inside the sets like this you can see we have a let's see oh you can see the first one is a big house at number one and if we say all houses last uh let's see if you can get the first does it have a last item no it doesn't we can get the first unfortunately and let's just say four value in all houses and then we type the value out in here let's maybe even print the value like this so you will see then the first elements inside all houses is a numbered house is a small house with that numbered house and the second one is a big house meaning that the two big houses couldn't actually occupy two separate spaces in the set simply because their hash values are the same okay so I think that's actually enough right now about equality and hashing we've talked quite a lot about them right now and I think you get basically the idea so there's two different things you have to implement or think about when it comes to equality hashing one is the hash of value which determines whether two objects should consume the same space inside a set but also you have to implement equality which determines whether two objects are actually equal to each other okay and also you may sometimes just need objects to be Equitable not hashable in in which case you can just implement it Equitable protocol or conform to the Equitable protocol as long as all the properties inside your structural class are equatable then you don't have to implement a custom equality static function however you can always go ahead and change the default implementation of both hashable and Equitable as well all right now we're done with equality and hashing so let's start talking about custom operators I'm going to close this playground in here so let's create a new one a blank playground like this and then we call this one custom operators all right and we create the playground then we say import Foundation like that and then we can get rid of the Explorer to the left hand side like this and we can run our playground automatically now we've talked about operators to this point uh quite a bit actually but we haven't talked about creating so many custom operators and that's what we're going to do in this section of the code so let's say that you have a first name and which is a string optional string and you say it is actually equal to Foo though it is set as being the optional string and then you create a last name in here and then you say bar now if you want to get the full name and you say it should be equal to first name plus last name you'll see that you get an error from Swift saying that this operator it is not defined between you can see there is no operator that exists that matches this particular signature left hand side optional string and right hand slide optional string if these were not optional strings then you would have this operator you can see that the error goes away let's see if we can get the definition actually for this one A Plus operator I don't think we can unfortunately let's see a static Funk Plus here we go there is that function signature all right however the Swift Foundation framework hasn't defined the same operator for optional strings so we can actually go ahead and do that ourselves so let's say we have a funk plus and its left hand side is an optional string and its right hand side is an optional string as well and it returns an optional string okay then we go inside the function implementation and we switch the left hand side and the right hand side if they are both none meaning that they're both null then we return nil or actually not null but nil Swift is one language that is chosen to use nil instead of null then we say okay if then we get the left hand side so if we say case let we have some value on the left hand side but no values to the right hand side then we return the value to the left hand side so if you only have the first name but not the last name then we return the first name as the full name we do the opposite of this for last name as well so if the first name is is nil but the right hand side has the value meaning that there is a is a family name then we say return that value all right and we can join these two together like this because they have the same pattern okay and then we say if both of them have a value so we say sum left hand side and some if I can spell some right hand side then we say return the left hand side plus the right hand side okay as soon as you're done writing this function you can see all of a sudden the errors go away and all of a sudden full name is indeed equal to Foo bar all right so um we can also add a space in here perhaps or add a space before bar so it becomes Foo plus bar right here okay so that's how you can create a simple custom operator in Swift okay and I think we've actually looked at something similar to this before maybe even something more complicated all right now we haven't yet created our own unary prefix operator this one was a binary in fix operator because it works with two or binary and things two things therefore binary so this is a binary in fix it is binary because it works with two operators and sorry with two parameters and it's an infix operator because it says in between two values okay however we haven't looked at unary prefix operators so let's create a unary prefix operator let's have a look at an example let's say that we have a lowercase naming here which is equal to foobar and we want to turn it into uppercase Name by saying lowercase name uppercase like this and this operator doesn't exist at the moment so you can see it is we want to say unary unary prefix it is unary because it only works with one argument to its left hand side and that's why it is called prefix because it is it basically works with some actually no that is a that is a suffix I would say that we need to move this here okay so this is a unary prefix because it operate cases whatever it comes to its right hand side so prefix because it is previous to the argument to its right hand side okay so what we can do then is to go ahead and implement this operator but before doing that since it is not an infix operator you actually have to Swift you have to tell Swift that it is a prefix operator so you do that by saying prefix operator it like this so you first tell Swift that this is a prefix operator then you go ahead and Define a function for it so you say prefix func like this oopsie lazy all right and then we work with a value of type screen and we return a value of type string then we take the value and we say uppercased oopsie Daisy uppercase like that now all of a sudden you can see that this error will go away and our Foo BAR value will turn into Foo bar as uppercase okay so that that is how you do a prefix operator in Swift you have to first Define it as a prefix operator then you create the function for it similar to this we can also create a unary postfix operators so let's say that we have for instance um a name here which is fool bar and we want to turn it into a star star star Fubar star star star like that okay so whatever string we give our operator we wanted to prefix it with three stars and a space and then a space and three stars after it okay so we say left with stars is equal to lowercase name and then make sure you start it out so meanwhon a unary post fix operator it is unary because it works only with one object to its left hand side and therefore it's called post fix because it comes after the element that it works with so let's define it we say postfix operator star and then we say postfix func star it takes a value of type string and it returns a string as well and what it does is that it just says star star space value star star star okay and then you can see the value printed here will then be star star Fubar space star star okay so you can also Define your own custom binary infix operators on completely unrelated types so it what we've looked at so far is that every time you work with a binary infix operators both left hand side and right hand side were of the same type however what happens if you have for instance a struct in here let's say we have a struct of person and we say let name is a string and then you have a struct family and then you say let members is an array of persons okay then you go ahead and you say that you for instance have a mom let's mom is person with the name of mom then we create a dad in here Dad we say that and then we say Sun sun is Sun like that then we create dollars so we say daughter one and his daughter one and daughter two all right now what we want to do in here is to say and we want to create a family we say family like this is Mom plus dad so Mom and Dad create a family together however this operator at the moment is not defined Swift doesn't understand what plus between two persons means so we can go ahead and actually Define that so we say we have a function in here we say funk Plus on the left hand side we take a person you see a person and right hand side another person so we say a left-hand side person and we say right hand side person I can understand that we said left hand side and right hand side are probably going to be different types and we've so far created binary infix operators with the same types for both parameters and we're going to do something different now so you're probably asking yourself so why aren't we doing something different but before we do that different thing that we're going to do we have to first implement this function you'll see soon okay so we first say if you create if you add two persons together we create a family all right then in here we say we create a family with members equal to this let's create these in separate lines like that the members are at the left hand side and the right hand side okay now all of a sudden you can see this error will go away and then you get a family in here okay so that's one thing now what happens if you then go ahead and say for instance family with sun is equal to family plus some hmm does this work no it won't because the left hand side of this operator is a family and the right hand side is a person and what we've defined is plus between two persons not a family and a person so what we're going to do is to go ahead and say func Plus on the LA on the left hand side we're going to take in and we're going to take in a family all right so we're gonna say on the left hand side we have family and the right hand side we have a person and this returns also a new family then we go ahead and we say we take the current families members family members then we append to it the current uh the person to the right hand side then we create a new family and return it with the given members like this all right and then you can then see that this error will also go away so you can say family dot members dot count and then in here you say family with sun members.com which should be one more than this family you can see it's three okay now what if you want to say family with daughters so let's say family with daughters and then you say okay take the family with the son and then add a whole array of daughters to this so you say daughter one and daughter two or S sorry not an array of daughters but an array of person you'll get an error now because we still don't have an operator that can work on a an object on the left hand side of type family and an object on the right hand side of type an array of person but we can go ahead and Define that okay so we can say func Plus on the left hand side we take a family and the right hand side we take an array of persons and this guy returns a family all right so the way to do it is to say VAR members again members equal to left hand side members then we say members birth append contents of the right hand side okay and then we return a family a new family with the new members like this all right so now you can see this error will also go away and if you say family with daughters dot members dot count then you should get the value of five printed to the console in here okay so you can see how easy it is to rationalize about how operators should work in Swift they're just simple functions except for unaryfx and urinary postfix which you have to also create these operator um tags kind of or declarations so this is the implementation of the operator and this is the Declaration of the operator okay so I think that is actually quite enough right now about custom operators in the next section we're going to talk about some of the new features uh inside Swift for a basically concurrency and asynchronous Swift and that is going to be the last section for this course and so without further Ado let's just get started with it I'm going to close this tab in here and then I'm going to create a new playground and then let's say playground and we call it async Swift all right and we just say we want to import foundation and here is one of the exceptions where we have to import three things we say import also playground support and then we import import concurrency concurrency like this and we're doing this playground support here simply because asynchronous code requires that our playground is active all the time and it doesn't just start from the beginning and ends and when the when it encounters the end of the file we just need the playground to stay alive simply because concurrent code and and asynchronous code requires that kind of behavior because if you make an API call that takes three seconds to finish maybe before that API call is done your playground has already reached its and it just terminates and you don't want that so let's go and say playground support sir playground page at dot currents page and then we say needs indefinite execution equal to true so if you're running your code on a Macintosh in xcode then you have to do this but if you're on Windows or Linux and you're in Visual Studio code I'm just running your code using simple Swift then you shouldn't really do this you should perhaps just create a simple project that can have a main Loop and then you can then execute your code inside that main Loop That Never Ends okay and however if you're in a playground then you will need to do this on Mac OS all right now let's say that we want to create a simple asynchronous function in Swift if you're already familiar with dart for instance for flutter or python or rust you probably have already used Tokyo perhaps in rust or in Dart you also have Futures and stream stream controllers you're probably already familiar with asynchronous code but if you're not I'll just quickly brief you on what it means it means if you have an asynchronous function it will not immediately return its result it can take any number of seconds or milliseconds to complete its work and return some value and perhaps it won't even return a valuesome asynchronous functions don't return a value okay so let's go ahead and create a simple dummy function in here which we call calculate full name so we say funk calculate full name all right then we say we have a first name first name is string and then we have a last name which is a string then we say it is an async function which returns a string okay so by creating this asynchronous function in here you'll have the ability to basically delay the return of your results so you can in here just say return hello you could definitely do that but that's not the point of async functions this is asynchronous function not an asynchronous function a synchronous function returns this value immediately and asynchronous function might take some time before it returns its value so let's go ahead and say we try to await on a task by sleeping for the duration of one second so this is how you would create a delay a fake delay in your function all right and we're using the try with question mark syntax in here because we're not throwing okay if this function throws then we didn't have to do that however we're saying that our function is an async function that doesn't throw let's also Mark our playground as automatically running so we say try and we say await and let's say cannot convert return expression okay and here then we can say return after waiting one second return the first name with the space and the last name as the result of this function all right that error is now going to go away now inside your playground if you want to call this asynchronous asynchronous function you have to create a task and then you can say let result 1 is equal to a weight on the result of calculating the full name the full name comes from the values of Foo and Bar in here okay and you can see the result is actually Foo bar all right it waited before it calculated the value for us then we can also go ahead I mean you can see in here we have let result equal to a weight but there is another syntax word in Swift which is called async let and you can say async let result 2 is calculate and so you can see how async is before the let and then we say take Foo bar again as the values and in here if you want to if you want to wait for the result of this you have to await on it so you say a way to resolve to now asynclet is a little bit more special because it creates a child task as part of this task you can read about it in Swift Evolution on GitHub and so I won't go too much into it but it is kind of similar to this guy uh but it has a little bit difference in like how you await on it because some developers think maybe that oh this by default awaits on this but it doesn't okay you have to wait on the result yourself manually okay so that's how you can create a simple task in asynchronous task and then do some async and a weight code inside it in Swift now we can go ahead and put together maybe an example that talks about async and async let's and tasks all together just to make it stick a little bit more okay so let's say we create a cloth enum in here and we say we have case socks we have shirts and trousers all right then let's create some asynchronous functions in here so we say the first function that we have is called buy socks all right and it is an async function that throws and we say it returns a clove and what it does is it says try a weight on a task by sleeping for a duration of one second and the reason this function throws is that we're not doing try like this if we did try with a question mark we didn't have to throw okay but we're doing just normal try therefore the function has to throw or it has to be inside I do but what we're indicating to the outside world by writing this function and seeing that this function is an asynchronous function that can internally actually throw an error so be careful while consuming its value all right then we return a close of type socks so after one second we produce an item of clothing after doing this one we can go ahead and create another function which is called by shirt like this and it produces an item of clothing and ins in here we just say shirt all right and we can create another one that produces a item of trousers so we say trousers and it says dot trousers all right so they're very similar to each other they just return a different result of them now you want to create a structure in here that is an ensemble an ensemble is a you can say it is a collection of clothing clothes items and you can say struct Ensemble all right and then we say this guy has clothes in it and we say it is an array of clothes and it has a total price price of type double all right doesn't really matter what the currency for the prices we also want this Ensemble to be printable to the console in a very nice format so we can form it to custom debug string convertible protocol and therefore we have to implement a new variable here called debug description like this we make it a computed property and then we say clothes equal to clothes and we say price is equal to total price so the value that you're producing here will then be printed to the debug console whenever you try to debug an instance of this Ensemble structure okay now we create a function in here called by whole ensemble like this and we say it it's an async function that throws and it produces an ensemble in here okay then we should go ahead and buy all our uh parts so we say async LED socks is buy socks async let shirt is by shirt and async lets trousers is by trousers all right so since all these are async let's then we need to await on them and also we should also sorry not also also twice now became four times so what we want to do is to go and create an ensemble so we say let's Ensemble on uh symbol is an instance of Ensemble and it says okay give me the clothes and you probably think okay I'm just gonna give it socks shirt and trousers but you can't do that because these are async let's items you have to await on them so just type a weight and then we go ahead in here we say socks a shirt trousers but since these guys are also throwing functions you have to try them okay so you say try try try and then for the total price we're gonna say the total price is 200 okay there we go and then we can return The Ensemble like this now all these errors are hopefully gonna go away so there we go now you can to test this you create a task in your playground and then you can say a flat Ensemble is equal to try a weight on buy hola Ensemble then you can say Ensemble is this otherwise something went wrong like that all right and then you can see our Ensemble debug description will be printed to the screen says clothes are this let's see if you can get the entire clothes maybe we could print it even so print it's a little bit easier perhaps to read it here there we go so it says is a shirt it's a socks trousers and also the price is 200 dollars let's say okay now async lab can only be used within asynchronous closures and asynchronous functions or wherever there is a task being run so you cannot use asynchronous async let within uh anything that is not one of the ones that I just described so it should be an asynchronous closure an asynchronous function or wherever there is a task that you have such as in here okay so let's let's have a look at a few examples we go in here and we just say funk get full name and we ask for a delay a fake delay and we say it's of type duration and we say we have a calculator for what we calculate like how we calculate the full name and it is an async function that returns a string in here and then we say it is async function add it in itself returns a string so our job is just to try to await on this uh task sleep for this delay and then we return and we want to return the result of this function but it is an async function so we have to await on it so we say wait on the calculator like this all right and then you can see all these errors are then going to go away and then we have our print statement in here let's just remove it so that we don't get this print in the console all right now that we have that we can go ahead and actually say we have a funk and we call it full name and we say it's an async function which is an error function and we just for now just we say Foo bar all right so it is an async function but right now it just returns asynchronous result back to us full name like this then we can create a task and we can say await on get full name and we say uh let's break these down and then we say the delay is in delay in seconds one and its calculator is indeed uh let's actually see for the calculator let's create a a trail enclosure in here then we say async let name is full name and then we can say return awaits name all right so let's see if we get the results printed to the screen now you can see Fubar then being printed to the screen so we could use async let simply because we're in a an async trailing closure okay and also we've been able to use asynclet in other contexts such as here which we're in an async function all right so I mean there's a lot more actually to talk about when it comes to asynchronous programming with swift but this just gives you an idea of the basics of asynchronous programs very similar to JavaScript and typescript and you could also say it's very similar to actually Dart for instance for those of you who do flutter development it's a little bit more complicated because well it is Swift it has a long history of its own code base and there are a lot of people contributing to Swift as a programmable language not even just people just inside Apple so it is somehow a mishmash of everything the community thought was a good idea to add to Swift I personally don't like for instance async let I think it makes things more complicated almost every other program language that has asynchronous programming such as JavaScript typescript and dart don't need async lab they just do async and a weight and everything works as expected I think async lab adds a new layer of complexity to your code which is unnecessary some people may argue that it is actually nice but I personally don't like it so much but that's just my opinion and I think it although I don't like it so much I learn it and I think it is important that we all learn how to use these syntaxes that are available in modern Swift so with that said I think we can then conclude this particular video of the full stack with swift course and we've talked a lot about you can see we have so many playgrounds in here I can't even count but we talk about variables operators classes expenses generics pretty much everything that you can think of in Swift so now what we're gonna do in the course is to go ahead and start talking about client development and also back-end development with Swift I really hope that you enjoyed this video if you found it helpful please press the thanks button at the bottom of the screen or you can just alternatively join my YouTube channel so see you in the next video