[MUSIC]. In this segment we'll start our study of ML's module system. This is a pretty big topic, it'll go on for several segments. Even though we're just going to scratch the surface and get the basic ideas of what we can do with the module system. So the motivation here is that so far all of our programs have just been one top level sequence of bindings. We might have helper functions or local bindings inside of functions, but we've just had that one sequence. And this is really not a good organization for larger programs you might write, and ML realizes this, and like many programming languages, it has more support for organizing larger programs. So the main thing we'll focus on are ML's structures. A structure defines a module where you can have a bunch of bindings that are separate from other modules and their bindings. So, in this segment we'll just go over the syntax, and discuss the basics, and then we'll move on from there. The main, construct we'll have in this segment, is the structure binding. So you say structure, the name of your module. It's conventional to start with a capital letter, but it doesn't really matter. Equals, struct, then any bindings you want, any kind of bindings, data types, exceptions, variables, functions, and then n. And then inside a module, that sequence of bindings is just like we've been seeing a top level. You evaluate each in order, later ones can use earlier ones. And then after you've defined the module Outside the module, you can use those bindings, but you can't use them directly. Syntactically, if there's a binding in there called bindingName, you write Module.bindingName. This is probably not surprising to us because we've already been using some of the modules in the standard library, and that's why when used a function like String.toUpper, it was the toUpper function definied in the string module. So what we're learning here is how to define our own modules. So I have an example here that I already had written out. this is a structure that I've highlighted right here, it's just a silly example. I've called it MyMathLib, and in it I've got three bindings, a little factorial function, a variable that's initialized through half of pi, notice I'm using the math library here which has already defined pi. And then a little function that doubles it's arguments. And now that's the end of my module here. And then outside the module I'm continuing my program and I can use bindings in the module. So I could say val pi equals MyMathLib.half_pi plus MyMathLib.half_pi, and val 28 equals mathlib.doubler of 14. So we can evaluate this program just like any other program. We can say name, space, management, dot SML and if we do that, we'll see that the rupple is telling us that there is indeed a structure my math. Lid, that has in it, a fact binding and half pi binding, and a dobbler binding then at top level, we have pi, which turns out to be 3.14159 and 28 which has value 28. I just want to emphasize here what is in our environment. We have, things like MyMathLib and dot fact. That's a function from int to int. We do not have in our top level environment, fact. That's simply not bound. Nor do we have a variable MyMathLib. These structure names are not variables. They're different thing and we have the modules but we have to use the bindings in them. We can't use the whole binding at once like you see here. There is no such thing as my math lib. That's just part of the module system. Which is a little bit different from the rest of the language. Okay, and of course, we can you know, say MyMathLib, mat, [LAUGH] MyMathLib.half_pi plus 1, and that will work just fine. except that I have to say 1.0 and then it will work just fine. Okay? So, what we have done so far is what I'll call namespace management. By using modules, we can keep the names for different bindings separate and this makes it much easier when you have a large number of functions and variables in your program. You can even have a whole hierarchy ML supports defining modules inside of other modules. And this is great so that a list library could have a map function and the tree library could have a map function. And they don't have to worry about calling them list map and tree map, each one can have a map in its module. Now this is very important for larger programs, but it's just not very interesting. this segment is only a few minutes long and it's kind of all I have to say about it. Yes you should use name spaces and we're glad that language is have them, okay. So, to finish up this segment just one optional feature because people always ask about it sometimes people want to know is there a way to say I want to to be able to use everything in a module without having to type out the module name. And you can. It's with this Open feature that is supporting the mail. You can put this inside of modules, you can put it in the REPL. I'm not a huge fan of it, because it tends to take all those well named things that were nicely in a name space and then open the whole module, which often has more than just what you want. But nonetheless, let me show how it works and how it's really not very necessary. For example, if I thought I was going to call half_pi a lot, I could just say val_hp equals MyMathlib.half_pi. And this works totally fine, and now we can say half_hp plus 1.0, and it works fine. Now, if you really did want everything in the module, then you can say open MyMathLib, and now, I have a top level binding for fact half_pi in doubler. In fact, is now in my environment. I think this is really useful for REPL when you are testing outer module, but other than that, I don't find it particularly useful, especially if you are thinking oh I really want to use fact a lot and you forgot that the module also has the binding doubler. You're actually, when you say open, going to shadow any doubler that might already be in your environment, None the less, if you want to use open, you can. It's in ML, it's in there for a reason. People find it convenient. I consider it an optional topic. And that's our introduction to module systems and using them for name space management.