 Yeah, so should we do go it's 26 over, so I guess we can go. Yeah. Yeah. Okay, so can you see my my my screen now this metaprogramming notebook. Okay, perfect. So first I'll give a quick motivation of what is metaprogramming and why is it important. Then as motivation example one quick application of metaprogramming so we will use a macro and macro is like the hero of metaprogramming and we will show how we can use macros to make code development easier and cleaner. And then finally we will talk about how to do metaprogramming ourselves so expressions in Julia and create our own macros. So metaprogramming in a nutshell is programming about programming. So when you do metaprogramming you write a code that writes code. And the reason for which you can do it in Julia is that Julia is what the language theory it's called homo iconic language, which means that in Julia, Julia code has a type. In Julia represents Julia code itself with the data with a data type. So in Julia you can represent Julia code. And so when I create a macro and in Julia macro as distinguished by this at symbol. So yesterday we saw something at the time. For example, if I run this it will time how long it takes to run this function. And what this at macro does this at macro is a function. Well it's a macro but what is a macro macro is kind of a function which takes his input Julia code. So the input of the macro is the Julia code. And the way is Julia code is represented is as an expression. So when he takes this macro it takes his input Julia code parsed in abstract syntax tree. So it knows the Julia syntax and it can like analyze it and modify it. And we will see it soon. And before we get starting to see how macros are used how to create macros and how to represent expressions. Let's see a simple example when metaprogramming can make our life easier. So I want to define like yesterday type struct my integer. Okay, which has just a type which is an integer, similar to what we did yesterday. Okay. Now, suppose I want to define the operations on these so I want to define addition multiplication subtraction division on the integers. I want it to do the same thing that would do a normal integers. So what I would like to define. I want to define that plus of X, my integer, and why my integer is my integer of X. I want to define my integer of X plus type a plus X plus why so just my integer with the sum of the integers inside my integers. And then I want to do the same for minus minus X, my integer, why my integer is my integer x dot a minus x dot y. Because I need to type a lot of mechanical code, because the structure is exactly the same operator X my integer y my integer equals to my integer attribute of the first same operator attribute of the second. And that's extremely annoying like I don't want to do it myself because I want to write a code which will generate for me all this repetitive code because I'm lazy. And so how do we do it. Okay, first, short interlude if I want to extend this efforts to import base plus minus times a division between two integers is not an integer so let's take just plus minus multiplication. And now I can define those functions, but instead of defining each one manually, I will write a macro in a for loop that does it for me. So I will start with a for operator in and now I give a list of operators or plus. And now when I put this column here, it means that it's a symbol. So this is the symbol plus. This is the symbol minus. And this is the symbol. No, of course doesn't work now. At this point, it's okay to think that the symbol it's similar to a string. It's actually very different, but for our purposes you can think of it just as a symbol indeed just as a string. Okay. Then what I want to do is that I want to define the plus of a my integer and be my integer. So what I would like to define this plus a my integer be my integer is equal to my integer a plus a plus a plus. That's my goal. And now if we observe the structure, the first symbol is the operator. So just like string interpolation, we do now expression interpolation so dollar sign up and this will interpolate like substitute here the value of up, which will be plus minus star. So then I will do a my integer be my integer equal to my integer a plus. Sorry. So now, if it's the first time you do this a thing you will probably do the same mistake that I was about to do. So you probably now would like to write a plus a dollar up be plus a it's a very common mistake I did it a lot of times I still do it. But that doesn't really work. So you cannot use you cannot interpolate the expression with infix notation. So you need to write it like this. Okay. This now is an expression. It's a valid syntax of Julia code. Because when I replace operator with plus this will treat the plus my integer a my integer be my integer equal to my integer of a plus a dot a. This is a, oh no. This is valid. See Julia syntax valid syntax code. And now I give these syntax this Julia code to a macro and particularly give it to the macro eval. So what this eval macro does it takes this Julia code as input. And well, actually it's just execute it so it doesn't do any manipulation just takes this code and execute it. And it will do when operator is plus minus multiplication all the time for each one. So let's run this cell now. And now you see I haven't defined plus I haven't defined minus. But now I can do my integer of my can do my integer one plus my integer. And it works. And I didn't need I can also do my integer show minus my integer three and it works and I didn't need to manually write that I've wrote a code which brought the code for me. So that's very cool. That's one thing where metaprogramming is very good at them. Why is eval needed here. It is because only then the op gets replaces. Okay, so this will become clear when we talk like about macros how macros are structured. But the idea is that the macro takes an expression and it well first you can do some manipulation then executes that expression. So we needed eval macro because we needed to evaluate this expression so we needed to execute the Julia code. Otherwise without the macro this would be just a symbolic expression would be just a set of symbols, but you wouldn't actually run the code. So can you show what happens if you just type in the expression without eval. Yeah, so just to see. Yeah, I mean, yeah, so if actually if I do like this it will run an error because now it expects that this is like real code. And I have this dollar op. But in a second I will show when we talk when we talk how expression structure. So, but long story short that is eval, it takes this code, it stores it as an expression. And then, well eval just executes it. So it does nothing it's like a trivial macro. It takes the code that stores this expression executes the expression. So just like a function x which return x basically but yeah you need to evaluate each one and then this dollar op interpolates the value of the variable op. So in this expression replace this op with the plus. Okay. And so this was one of the main applications of macros which is avoid the repetitive code. But if you have a lot of functions which are very regular, you can write a macro which generates all the codes for that. Now. So we, I have mentioned these expressions. But what are expressions. Well, that's the fine one. If I type just normal Julia code like this equal one and this is a trivial Julia code. If I put it around the parenthesis and put a I'm terrible with punctuation column a column before it. Yeah. I'm not sure if you meant to make this so markdown or not, but there's no syntax I think because of no I didn't say this markdown. Yeah, thank you. Okay, so if I take Julia code, rub it in parentheses and put the column about before it. It creates an expression. So this is an expression and an expression is a data structure to represent Julia code. So the only limitation is that the thing inside expression must have a valid Julia syntax. So if I try to do something like for example, these. This is sometimes how you represent and half of an interval but this is not the valid Julia syntax. It gives an error, because this is not valid Julia syntax. But if I give a valid Julia syntax like this, then this will make the font a bit bigger. So probably by using the windows. Okay, that works. Is this good. Yeah. Yeah. Yeah, sorry for that. Yeah, so if you give a valid Julia syntax, an expression is just a data structure to represent Julia code. So what this eval macro does it first takes this Julia code, you can think it puts these parentheses and colon around it so it stores it and expression. And well, the eval is very trivial because it just executes the expression so just returns the expression executes it just like a wax on wax off. But in principle inside the macro, when you get the expression, you can do modifications you can change it you can alter it to Julia code that you can add pieces replace pieces, remove pieces. And to understand it. Let's see how the expression is stored. So the fundamental function when we work with the expressions is a dump. And sometimes I tend to write down by accident and not be included just like me. So if we dump the expression. Now this will print the internal representation of the expression. And this is what the computer scientists call abstract syntax three. So I don't know how many of you are familiar with the concept, but basically you can think of an abstract syntax three of as a representation of the expression so here this was the expression a equal one. The head tells us what is the outermost operator. So when I do a equal one. This is like the, the thing that I executed when assignment. So it's telling me that this expression is an assignment operator. And then it gives the arguments. So the, as the arguments, the inputs of this assignment operator are a and one and they're stored here as a list a and one. Let's take a slightly bigger example. So let's create an expression, which is a plus B times the C for example, like this. Okay. And now let's look at the abstract syntax three. Now we see says that this is a fun a call. So this is like a statement that execute I sort of like call this I execute this line. And then says what are the arguments of this call. Well, the arguments is the first is this symbol multiplication. So this is the outermost operation now. And these multiplication has two inputs. Now, the expression and the symbol C. And this expression here is this a plus B. So it's this again, this a plus B is an expression which is a call. So it's like a statement which execute the and the arguments are the function which execute the and its inputs. And if you want it's actually a very funny exercise I suggest you to do that you just write Julia code that wrap it inside the make it an expression and study what it looks like. So this is like a nice way of like, how would I say good procrastination study how Julia code is represented, for example, we could do that the expression is if a is greater than one good like this, then know if what I want to do. I mean, for example, we can create an array 123 plus 123 that's valid Julia syntax. And then we can look at how it's represented. And now we see this is a function call. So the first thing argument is the function which I call so I call the plus operator, the second and the third are the inputs of the function. And the inputs are again expressions and what expressions were a vector an array. So this here is these array vector inputs 123. And this is this array vector 123. And now maybe you start to see like the cool power of metaprogramming and macros. It's that if I get this expression representation of Julia code, I can go through the tree I can change the things I can modify and create a new Julia code. So, for example, now I have this code, this expression 123 plus 123. And now suppose I want. So I want to see what it is I want to check the head of the expression, I can do X dot the head. And you'll say that this expression it's a call. Then if I do head dot the arcs. It will. Yeah, X dot. It will print the list of arguments. And now, for example, if I want to change the plus to minus I can do X dot arcs one. So the first one, the plus and I can replace it with the minus like this. And now if I look at the expression again. Now it's 123 minus 123. Another is that now I have a data structure to represent Julia code, and I can play with the code I can do whatever I want with the code. However, with great powers come great responsibilities. So this going through the syntax tree and checking that it's by the syntax is what the compiler generally does. Now, if you are yourself messing up with the syntax tree, you now must ensure that you don't destroy the syntax tree. You don't like destroy the code and you don't introduce invalid syntax. So now, for example, if I would replace the minus sign with something that doesn't make sense like a true. Okay. Yeah, now it, it creates this known sense where it's not sense. Can you have a function in true? I don't know. But anyway, even if it's theoretical love that would argue it's not with practice. So now, when you replace the minus you said that now I'm a function called the true which is called to two arguments, vector 123 and vector 123. And this is names are not allowed to start with numbers. Okay, so I guess at least in in actual code. Yeah, I guess we can try which are two valid. Oh, yeah, because now I give you so eval x. Yeah, and now it says no that doesn't make sense you cannot a integer is not callable. The reason why I used the eval function and not the eval macro is that now this x is already an expression it's already written with the parentheses and colon. So it's already like stored as expression, the eval macro it's used when you write as Julia code so without money put in the parentheses like that. Yeah. Now, to give a taste of why metaprogramming could be useful. Suppose you want to time a function so yesterday we saw this at the time round, which can measure how long it takes. It's not the best way to benchmark but it's okay. Now for the purposes, if you want to time how the function, if you want to measure how long a function takes, how would you do it like manually if you had to do it manually. Probably like start by first like setting a timer so something like this start equal time now that's not the right function in Julia I don't know how to get the current time but you like to something like get current time something like this. Then you would execute the function measure the new time at this top get the current time and return this top minus this start. That's what you would like to do so you would like to wrap the function that you want to measure inside these so first set the timer run the function. Take the new time and the difference is the measured time. And you don't want to do it manually every time you don't want to write all the lines this way. So what the time macro does in practice it does exactly this. So it takes this function and then puts some other code before and after it. Now you probably don't believe me so I show you. I went looking for the source code of the time macro inside the Julia source code, because you know it's open source so so everybody can read the source code. Okay, I guess it doesn't matter if it's a little out of the cell so that's how the macro is defined. So this expression starts with macro similar to function but now it's macro, the name of the macro and the input so this expression. And now, if. So this expression is the code that I'm giving it in this case it would be around. Okay, quote and it's just another way of doing the parentheses and colon. So if it's a longer code it might be annoying to write in parentheses and colon. So you can do quote and write longer pieces of code. So it's but this is the same of creating expression so this is an expression. It creates expression with what and then it adds some code before. I don't know what it is some compiler heuristics but you see it's at some point it takes the elapsed the time. So it measures the time before executing. Then now we have this dollar X. I'm not going to talk about this ask because it's a little beyond, but forget about ask at the moment. This is similar to what we had before so dollar X the interpolation. So now it's assigning the result of this function to a local variable. And then it's measuring the time again after the execution and subtracting the starting time from it. So you see it's wrapping these lines of code around our original code. And that's what a macro does. It allows you to manipulate code like add code, remove code, modify code. So it's a very powerful way to create code. And one peculiarity of the macros is that a macro master return an expression. So this quote and is an expression and the expression which is returned is also executed. So this actually what a macro does it. Now I want my cloud. What a macro does. So first stores the input code as expression. It does something what you want to do like add the code before the code after and so on and so on. Return an expression. So you remember from yesterday in Julia. The last line is executed. So this is like return what and so it's returning this expression. And evaluating the expression. Which means it converts it back to Julia code so from expression to Julia code and it runs that code. So basically with a macro it's what I would do what I did before manually you remember I've wrote the expression manually and then I use the ball. The macro does this writing expression and eval in one step. There are questions. Not in the chat. Okay, no. Do we have time for a small demo. Maybe. Before that. I will start writing the feedback section. Oh, yeah, that's a great point. Yeah, that's a fantastic. Okay, well just, I'll just do the end speech so I mean, I don't have much to say except thanks for for joining us for coming on the course thanks also for the great questions and for helping us improve the material for later. Yeah, I will basically write the same kinds of things that we had in the, in the feedback section yesterday. I will also add a separate question about each of the sections. But yeah, just anything just write something positive also. But especially anyway we can improve this course because he are running it for the first world essentially the second time. Yeah, really the first time. So, yeah, thanks for attending and I will let Luca continue while I write it back and be so it can then go over time if you want to. So that's maybe a little too mathematical example, I'm sorry for, I hope it doesn't bother anyone but basically the Wilkinson polynomial is this polynomial defined like these are so for example, like X minus one times X minus two times X minus three times X minus four times X minus five would be like the polynomial of degree five. So you see the structure it's harder to explain in words but when you see these I guess you get the structure like X minus one times X minus two up to X minus five. And this is an example where. Well, you could write a function for that so you could write a function Wilkinson, which takes the order and and the point at which you want to evaluate. And then you can compute. So this would be the product of a minus I for I in 12 like this. That's pretty much rewriting the function. So I can create it like this. And the last thing that I could also do is that I would like to generate this expression. So as I did here manually I brought like manually that the P five of X is this I brought manually this function. And what does what are the advantages of like writing like this, compared to writing like this, the advantages is this is now a constant expression so the compiler can optimize this can do some smart things. X minus one up to X minus five it's still okay to write manually, but I don't want to write manually X minus six X minus seven until X minus 100. Okay, so I would like to. I would like to create this expression, I would like to generate this expression so what I want to do. I want to create a macro. Make Wilkinson and which takes as input a number and and returns this function creates this function. That's what I wanted to do. I want to write a macro which generates for me a function to compute the Wilkinson polynomial of a degree and and okay, let's do it. So when I created this macro is and is now a number. So first I initialize my expression so X now this X minus one and must be at least one will be X minus one like this, this expression. So now I want to add the pieces to this expression. So what I want to do is that for I in to when I want to add the X minus two X minus three X minus four and so on until X minus and. So what I will do X. Okay, is an expression. And then the first part will be X. And now I must use this dollar sign because I'm interpolating inside the expression. If I just wrote it like this. Then it would just put the symbol X here, whereas I want to put the content of the variable X inside the expression. So I must interpolate. And then I add the piece, which I want to times X minus. And again, now I must put the dollar I, because if I wrote just like this it would add the X minus I like it would add these to the expression. When I put the dollar it interpolates it and creates this X minus I. All right. Okay, let's change the definition little that let's have it also take a second. Parameter which is the name. Okay, so the order and the name of how I want to call the function. And then I want to construct the function I want you to look like for example that if the name is p five p five of X equal X minus one times blah blah blah. And this X minus one times blah blah blah. I already constructed here. It's this one. Now I want to add this piece here. So again what I do, I create the expression name so now I'm interpolating the name. And X equal. I'm not sure but let's put it to be say X equal X. So now in this expression here inside the on the right side of the equal sign will put the content of this expression. And on the left side will create replace the name with the value of the name that will create an expression which looks like this. And since this is a macro, this expression which is returned will also be automatically evaluated, so it will actually like generate the code and execute the code. So let's write. Now, suppose I want to call the function p six. Let's first prove that I don't have p six p six not the final. I want to make Wilkinson six degree six and I want to call it p six.