 the first slide. So we're kind of done with our epidemic simulation except we might want to turn it into a package that people can install and use directly. So to do that let's go to the creating packages section. All right so here we'll talk about first modules because modules are packages contain modules, modules contain functions and type definitions and other definitions values. So we'll need to go through how to write a module in order to write the package. Then we'll talk about packages and testing and then there is some about naming conventions and how to make your functions pretty and things to remember about variable scope that are good to know if you are actually writing a package that someone else might use, especially the naming conventions part. All right, I'll just continue sharing this for a moment longer. Okay so yeah so we've been using basically the notebook interface so far and REPL, so what you get when you type Julia that's called a REPL. Those are good for development for changing things and testing them and sort of doing rapid changes but at some point it will get limiting to always have to run the notebook and it is easier to automate things in a text file. So that is I guess mainly to use for scripts. That's when you start writing a script. You take the stuff in a cell in the cell that's getting really long or a bunch of cells you tend to always run in the same way. You take those and you put them in a file and then you can either include them so that it doesn't take too much space or you can run them using Julia some file name.jl and run the whole process. So that is scripts are basically just for automating a workflow. Now at some point you will also run into the point where you have a lot of names, a lot of variables or function names, a lot of stuff that is kind of all tied to doing the same thing all related to each other and then it makes sense to create a module. So modules work a lot like what we've seen packages do so they contain other names. So a module is essentially just a container for a bunch of functions and bunch of structures or types and you can refer to them. You can either use the using keyword to get some of that stuff directly into the main namespace or you can use module name dot to refer to anything in the module. Okay, so this is how you write the module. So you start with the module keyword. We'll actually just demonstrate this. Where is my demonstration notebook here? So you start with module. Let's call it my module. You can have the export keyword. So anything that is exported will go into the main namespace when you use the using keyword to get the module. My cool function. Okay, and well the module ends with the end keyword. In between you can define a bunch of stuff. So let's define a function, my cool function, which I have already exporting here. It will just do some printing. So this is a function. End. Let's define another function, but we will not export this one. So this is my secret function. And what does it do? It prints, you found it. Okay. So when we run this code, end, expected end in the definition of my secret function. Oh, I'm actually missing parentheses here. Not the best error message, but it did the job. I figured out what was going on. Okay. So this defined a module called my module. It's actually main.myModule now because I didn't do it in a file. I didn't do it in a package. I just did it in the main namespace. So I now already have this main.myModule. Okay. Tab works to complete. So I can add a dot and tab to list all the stuff in there. These are standard in any module. And these are the two things I actually defined. By the way, you can also define, let's say x equals two. Now it's warning that it's replacing it. That's fine by me. So now it also has an x. Okay. So yeah, you can inspect and basically see all of even the secret function in there. We can also use the using keyword. But now we have to do main.myModule. So this works. And now we have my cool function, but we don't have my secret function. It's undefined. It is still in my main.myModule.mySecretFunction. So this will still work. You found it. Okay. So yeah, the basic idea is I have a bunch of stuff that I've written for one specific purpose. So it makes sense to group them into a module to keep track of things. Now I could put this into a file. In fact, I have here. So I can have this in a file. I think it's in notebooks. MyModule.jl. This is without the x equals two here, but otherwise this is basically the same. And then I can use the include statement to include that file. And it will, because it just takes a text in the file and plots it in directly into my code. It's the same as having this in the cell. It will give a warning replacing my module. Right. Okay. Because it's in notebooks. So this is the wrong path. So it will give a warning replacing my module. Okay. So that's kind of an easy first way of defining a module or taking some functionality you have coded and putting that in a file in a way that kind of makes sense. But you have to use the include statement. You have to know the exact path to the file. And the module calls into this main namespace, which is kind of annoying. You could possibly get around that. I mean, actually, there is a way you can just say dot. Oh, it has to be in a using statement. So you can say using dot my module. Okay. It keeps giving me warnings because I keep re-importing the same module. But still. So you can just say dot my module instead of main dot my module here. But still, it would be good to not need to know where the file is exactly for this include statement. And it would be good to not need to specify where in the namespace the module is. And that's what packages do. So packages are collections of essentially it's one module, one main module plus bunch of other modules. It could be just the main module. Just one module is enough. That is Julia puts in a place where that it knows where it is. So you don't need to specify the path. Julia knows where it is. So you just specify the name and that's enough. Now packages also have some more information like dependencies. You can specify all the all the libraries, all of the other packages that this package depends on. And when you install your package, it will automatically find and install those dependencies. And it can also define tests that will be run automatically. Well, that can be run using a single function called package dot tests package dot test. But yeah, that's basically all the explanation needed here. We already did an explanation of the import. So we don't need to do that part in the notes. One thing that you commonly see in beaker packages is not really doesn't really make sense here, but you could that you can in beaker packages use the include keyword inside inside your module. So you could, for example, define this function my secret function in a file and then include it here. Now, since the function is really short, it doesn't really make sense to do that here. But sometimes you have such a big module that you want to separate it into a few different files. You can also create other modules and then you can use or import let's say, you can say using example, you probably want to do that on top here. And I probably want to keep my second function. Okay. So yeah, you probably want to do that on top, maybe after the export keyword like this. Okay, or import works just as well. Now, even if you use using this example will still only be inside my module unless you want to export it here. So running using example inside a module doesn't mean that all the stuff in the example module goes into the main namespace as well. All right. It's 12. We'll be a good time for a break pretty soon. Let's do one more thing. So we have been using these packages package package to maintain our packages. So you know how to add install a new package and did we really do much else with the back? I mean, we did package.add and package.build in some cases because we had problems and so on. And so this is a relatively familiar package already. One more thing, it will, we will go to a couple of new things to do with this, but there is a function called package.generate, which you can use to create a template for your own package. Now there are better templates out there, but this is the basic template. We'll take a look and extend it a little bit. But yeah, Luca, remind me to mention or put in the notes the templating as well. I can add in the hack and denote about this package template, which is kind of more advanced and sets the whole structure for tests and documentation. But this is the basic package template. So we'll create a package called my package and then just see what it does. My package already exists. Right. Okay. Let's go to Jupiter. And I think the best thing to do here, I mean, I could just show you what's in there, but let's make sure that it's fresh. So I'll delete the folder and then run package.generate. Okay. So I'm not sure if this has any readable content to you. It has the name my package here. That's pretty much it. But it has created a folder called my package. Inside that folder, there is a source folder. That's where our Julia source files go. And it has in fact created a my package.jl file. Now, you need to have a .jl file with the same name as the package in the source folder. And that contains the main module for this package. And this now, as an example, contains this create function. So in the my package.jl, you need to have a module called my package of just package name. And again, that is the main module. So when you type using my package, it will, that will not work quite yet because we haven't added this package, but it will import this module. Okay. So there was another file project.toml. That's kind of unreadable at this point. Well, it has the name. It has a unique identifier for your package. And it has some information it put from my Git. Is it from Git? Or is it in a separate place? It might ask you for your name and email. And a version number. Now, we will be adding some, I mean, we will be using the packaging system to automatically add some information here. You don't need to manually change this file, but it contains the information necessary to install this package. Okay. So before we go on a break, let's do one more thing. Let's use this package. So if you haven't been typing along, please type this using package and package to generate. And then let's, then we'll do package.develop. So this is like package.add except that when we change the contents, it will detect that and update the package. So if you use package.add, it will just go into some folder in the Julia path that you don't even know about. Julia knows exactly where it is, but you don't. And you cannot actually then change it without, at least you have to manually run package.add to change it. So doing it this way using package.develop means that it will follow your changes in the directory. The way I was recommended to do this, it's using a function called package spec, but maybe Luca, you know a better way because having to run two functions is more than I would expect. But you need to provide the path to the develop function in some way. And that is for this package spec method. So the path to the package is now just my package because we just created it in this folder. But this needs to be actually pointing to the package. Okay, package develop my package. Takes a moment. Okay, resolving, updating. So it's a lot like add. It's basically the same kind of output. Okay, and then we can use it using my package. Okay, pre-compiling. And we can run a function. So since we are using it, oh no, because this one doesn't export anything. So we didn't get any new function, the main namespace, but we do have my package.grid. So that runs this function, which brings Hello World. Okay, a bit of a whirlwind thing, Tor, if you are not that familiar with package development, don't worry, we will go through these steps essentially again when we create our epidemic package. But before that, we'll talk a bit about environments and handling dependencies and so on. The important thing though is that we have told Julia where my package search AL is, I mean, Julia created it, but we could now, we could copy paste our entire simulation here. And then using my package would give us all of our simulation functions. We will actually rather call it the epidemic or whatever you want to call it and create another package again, just for repetition and for exercise. Are there any interesting, important questions before the break? Right, yeah, you can watch through, work through Lukas package development in Julia. It was a few weeks ago. So that has a lot of more advanced information. But yeah, unless there is something else, so something in the chat. So let's come back in half an hour, create a new line at the end somehow. Sorry, it didn't work as I intended. So when do we come back? 1240, that's the type record then. So it is time to continue. So this was completely expected, but still we don't have time for everything. Oh, one thing actually that I was going to add here strings and IO. So we don't have time for everything. So I've added a list of topics that we have prepared for. So please vote on the one that you would like to see. I guess you can vote on multiple. Why not? Yeah, we'll just do the ones that with the most votes kind of in order and we'll see how many we have time for. Yeah, I think we can allow to vote on everything. It makes sense. Of course, if you vote on every single possibility, not exactly change much, but you can do it if you want. Okay, so let's finish the creating. So the testing is actually just a testing part in the creating packages section. You can read up on your own. Testing is a relatively big topic in general, but to do it just in practice, maybe would be, I don't know, it might take an hour, it might take five minutes. I'm not quite sure, depends on how we do it. All right, anyway, let's continue with the packages, which is still somewhat more important than testing. So we generated a package and saw the contents. So now before we do, we will essentially have an exercise where you create another package and copy paste all the epidemic content that we have into there and then make it usable. Now, before that, we'll need to talk about one more topic. And that's development environments. So if you've done any extensive development in Python, for example, probably also in other modern languages, you will probably have a user development environment. Otherwise, this may be a new topic. So we won't go into all that much detail, but hopefully enough that it makes sense why this is a good idea to do. And we'll do this using the My Package package. So just as a reminder, there is a folder called My Package here. And that folder contains this project.toml file. Now, this isn't just for packages. Any folder can contain a project.toml. And that can then contain a list of packages that whatever the project that you are working on in that folder needs those packages. That's just a good practice thing to when you pass a project onto someone else, they can run it because they know what packages are needed. Now, development environments automate most of that work. So first, we'll need to specify a project. And to, again, use a package package, so PKG package to do this. So to specify a project, you actually specify a folder. And then that folder will contain the project.toml file. Let's use my package. Now, again, it can be any folder. This happens to be a package folder. And every package folder will contain a project file. Okay, so first activate my package. Now, Julia will basically, so this, okay, yeah, the way it automates making sure that all the dependencies are listed is that it will pretend that if a dependency is not listed there, you haven't installed it, right? So if I do using plots, we already installed plots in the previous exercise. So I should have it, I in fact do have it on my system. But it says package plots not found in current path. So I have to actually install it to be able to use it package.add installs packages. I need to install the plots package. It shouldn't take, I mean, it will check if there's a new version. But the installation is extremely quick, even though there's a lot of packages, because it didn't actually install anything. It just made sure that I first of all have it on my system. And then it listed it into project.toml file, which is unchanged. So there's in, okay, I probably just needed to reload it. Yeah. So plots is there. So now I can use this to whenever, in fact, whenever I, whenever I install this package, it will automatically install the plots as a dependency. Also, there is this manifest.toml file, which contains much more specific information on exactly what packages I currently have. So you can also use this file to reproduce exactly the environment that I have right now. And there is a function for that that's instantiate. So first you activate the project and then you instantiate. But yeah, you will find that on Google if you run into the situation that you need to exactly reproduce the environment. Okay. So that's basically it. In order to quick recap, because this is a very, this kind of a subtle thing because it doesn't, it didn't do much, but it's a very useful thing to do. It's a very important thing. So first you create the file project.toml. When you run package.activate and the folder name, it can be dot for this current folder. If the project.toml doesn't exist, it will create it. Then the idea is to list all the packages that you need, all the dependencies in that project.toml file. So to make sure that you are not forgetting a package, Julia just pretends that the package is not there unless it's listed. So you need to run package.add to add it into project.toml. And once it's added, you can actually use it. So let's just make sure that we can use it using plots. So yeah, that works. And I can use it to plot something. Right. Okay. So this way you always know that when you hand your project over to someone, when you hand your, when you put your package on GitHub, anything like that, people can run it because they will know what the dependencies are. Okay. So that is about that topic. So then let's go on to the exercise, which is also recap. So create a package. So what I want you to do is to create a package called Epitemic. And so use the package to generate function and you will also need to, and then basically install it, add it using develop and package spec functions. Then you will see that there is a project.toml there. Activate that. And I mean, you can skip the test package since we're not going there right now, but install any other packages that are needed to actually run the simulation. I think plots is the only one if the animation function is actually there. Okay. Yeah. And then so yeah, you can go ahead and start. The epidemic.jl is here in the root folder of the source material. It has using plots here. So you will need plots. So then just copy all of these functions into the new module you have created. So into the package. Then you should be able to do using a, let's skip exercise too because it uses this grid package, but let's not do that. I mean, it uses this grid function from the default package. Let's just go into it. So do exercise one, create the package, and then exercise three. So paste the contents of epidemic.jl into the source into the module and then use, add an export line and export everything you need to run the simulation. Okay. I will give you 10 minutes to do this, to get ahead of me, and then I will start walking through. So yeah, it is in fact a good point that we activated the my package environment. I also have it activated. So running package.generate will work correctly. So to create the epidemic package, I would run package.generate epidemic and it created two files. So now there is a file called, you cannot see the whole screen. Okay. There is a folder called epidemic. It has its project.toml and a source epidemic.jl file. Okay. And this is exactly the same template with the hello world that we saw before. Okay. Now to start, so that I can install it in the normal way while developing it, I can use package.develop. And for that I need the package spec function to get the package from the path. So another path is epidemic. Okay. Not found in project manifest or registry. So is this the problem you saw? Was it path equal? Yeah, path equals. Right. Okay. Now it works. But now it did put it in my package slash project.toml. And now I'm actually interested in seeing. So yeah, if I reload this file, it now has the epidemic package as a dependency. Yeah, if that happens by mistake, you can always delete it. Let's just keep it there. All right. Now I'm actually interested in so what happens if I deactivate the my package environment. So this will return me to the base environment activated environment at and it tells you what it tells you where actually your base environments project.toml file is. So even your base environment has one. Let's see. Using epidemic. So it's not in my base environment. That's interesting. So I can install a package so that it doesn't go into my base environment. Okay. Well, what I have to do then is run this again. Now that I am in my base environment. All right. And it did a bunch of updates. But mainly it has added the epidemic package into this. My, my base project.toml file. Okay. And now I have some extra stuff here. So that now I can run using, sorry, using epidemic properly. Okay. Now the idea was to go. So this is the epidemic.jl file. The idea was to go, I have it open a different window here to go into epidemic.jl and just copy everything and put it into this source file, this epidemic.jl. So let's put it here. Okay. And now I can run using epidemic. And I'm not exporting anything. But I can still run, let's say, make plants. Well, let's just use a tab to find out epidemic.jl. Oh, it did an update. That's annoying. Yeah, that's the typical trap that if you don't have revise, you if you're not using revise to track the changes. So the develop doesn't do that alone. No, it's a typical of Julia that if you want to track the changes in your source code, you should use revise to track the changes in the package. And then just updating the source code will like track the changes and update. But if you're not using revise, then you should well, basically, you have to restart. Yeah. On the bright side is that if you use Visual Studio Code for development with Julia extension, then that will actually use revise by default. So it will work without you having to know it. Yeah. But actually, I'm not sure it's a good thing that it works without you knowing it, because then when you are somewhere else, it doesn't work. Yeah. So the take home lesson, I guess, is that if you want to develop packages, check out this revise.jl package. It's fundamental for your workflow. Or at least, if you want to develop packages in using the Ripple, test them using the Ripple or using an old book. If you are, if you're running scripts, then this will always work because. Yeah, yeah. Anyway, now we have restarted the kernel. Sorry. No, I mean, by packages, I guess I meant more library, but yeah. Yeah, okay. Well, I guess the difference is libraries are bigger. Yeah, I guess I mean, libraries are generally packages. I'm not sure if it goes the other way around. Okay, anyway, so now we have updated the kernel, restarted the kernel, they run using epidemic again, loading plots into epidemic model from project dependency, which are okay. So there is using plots here. Maybe I should just make this bigger or just make the windows smaller. Okay, so there's using plots here, but in fact, the project.toml doesn't contain plots. So I have it installed so things will work. But it's not a very, it's currently not very stable. If somebody else tries to install it, it might break. So, but yeah, we can run make plants. And that takes I think two param, no, three parameters. In fact, 32, 32. And it has an immunity rate, I believe. Yes, it does have an immunity rate. So here's the source. And immunity rate is the probability that a cell is created as immune instead of uninfected. So let's create some immune plants point two. Okay, so we have a bunch of plants that are showing as empty wide rectangles because they're not infected. Now, okay, so in order to make this, well, yeah, so we can currently run the simulation, we can do epidemic.update plants. And that will run a single time step. Plants is not defined, because I didn't put it in a variable. Plants equals. Okay, let's just do plants equals. Okay, and now I can run updates. Sorry, I need three numbers here. We used eight time steps for recovery, 0.02 as the death rate and 0.1 as the infection rate. And to see the difference, I need to print plants. Except it doesn't really, the matrix is too big, so it doesn't look that great. Okay, but it is running. Let's say two colors.plants like this. Two colors is not defined. I think if it's defined in the package, you need it's not exported. Sorry, yes, this is exactly what I was going to get to in the next epidemic. Okay, right. The first time you run it, it compiles it, so it takes a moment. But there we are. So, yeah, to get rid of this epidemic dot, we can do a bit more work. So, we can go here and write export, and then list all the functions we want to export. So, we want to export make plants, probably update. Two colors would be good. Anything else? I guess that's it. Maybe count infections and count deaths. Okay, now again, if we restart and then run using epidemic, we will get make plants directly. We will get update directly, and we will get two colors directly. Now, it's still complaining to me about the fact that the project.toml doesn't list plots as a dependency, but it does run using plots. So, to fix that, I will do what we just did. So, right now, we can run a couple of updates here. So, we have a lot of immune cells, so it might not even get very far. Immune plants. So, yeah, to add the plots as a dependency, you could do it by hand, but I mean that this, I have no idea where to get this, and you shouldn't need to know. So, we'll do package dot activate epidemic. I mean, you shouldn't need to know because you shouldn't be doing that by hand. There's a much easier way to do it. So, you do then package dot add plots. Package is not defined. Yeah, so we need using package. Okay. Plots is not right. It needs to be a string because plots itself as a variable is not defined. So, it actually fetches the latest version information from the registry. Since there are no updates, it doesn't actually install anything, but it does find the latest version information for all of the dependencies of plots. And then project.toml gets the version string for plots. It also created again the manifest.toml, and that gets version strings for everything. Okay. So, now we have an epidemic package. We could put this on GitHub and, like Luca mentioned, directly install it using a GitHub reference, or we could even list it into the package repository. I guess a small comment could be that if you want to register in the official Julia registry, there are a few requirements on the package. For example, in the license, there are some requirements on the names. You need to specify at least the compatibility with Julia versions. So, for example, this wouldn't go through because you don't have a license and at least because you don't specify what is the minimum Julia version, which works with them. I think the name would be fine. Yeah, we are also missing some, we should have tests that may not be a requirement, but that's a good thing to have. But yeah, this is the basics. And at least you can install this with a GitHub address, a URL. Okay, but yeah, that is all I have about packages. So, it looks like we are going to go into macros and metaprogrammatics. Should we have a break before it, or should we go straight now till the end with metaprogrammatics? We started at 22, right? So, we've been going 35 minutes, I mean. Yeah, but I think yesterday, one feedback was that after the launch, we had the whole session with only five minutes in the middle. So, that's why I'm asking what people prefer. I mean, we should at least have a 10-minute break at some point. But yeah, we could do it now. It makes sense to do it now. Yeah, maybe green or red, green mark, if you want to have a break now, or red mark, if you don't want to have a break now, if we could have a quick feedback about that. So, you, I don't want to have the break. Because then we have a longer session. Yeah. No, I'm just testing. Yeah. So, 10 minutes break now, 10, 5, 10. 10. Yeah. How long would the break now? Yeah, that's 10 minutes. Yeah, 10 minutes. Yeah, 10 minutes and then a short introduction about macros and metaprogrammatics.