 So, if it works then it is supposed to come out like this, so you do using Winston and plot 1, 1, 10. You need, if you have a group plot installed, it works. Do you have a group plot? Okay, then that should not be a big download. Yeah. So, this side. Yeah. Okay. So, this is the stuff. Did you anywhere close? Okay, nice. How much, I mean, you do probably a little bit of sentiment analysis. Yeah, yeah, we do sentiment analysis. Just in the past. Just in the past. The total data that's there. Of course. This is some entity recognition. Yeah. It's failing. That's what I was showing you. Okay. What is. What? I think. I was in touch in. So, this is the basic. If you have a paper or something, which I started off with creating attack clouds, but it gives the. No, no, no, this is long. Okay. So, this is the. It seems to be failing. Yeah. It's probably some simple thing that can be fixed. Dependency issues. I suppose so. No, no. It's probably just some C code that requires some byte level, whatever. Some pointer format or some, you know, little, you know, little, you know, you know, little Indian, big Indian or something. So, if we had access to this machine, we would have done something about it. I see. I see. No, no. This is working on an arm machine. This building is running on an arm box. Okay. Fully on arm. Okay. So, this is. So, that's how Debian brings up. So, it's an army L. Where it takes data. There's an arm hf. I don't know the difference. So, that's all. So, it's a chain of processing. Okay. So, for example. But we don't work on that. It's not strong, but it just takes the data structure of strong. Okay. Here it gets further. And this seems like LLVM doesn't work on this thing or something. So, this helps to establish a pipeline or something. So, we say it's a tagline. So, LLVM also supports arm. Yes. It is also seen on this. Well, they claim on the website support it. But there are so many variants. So, it's hard to tell what support and not. And we can add more steps to it. So, even if. I think even if. I'll tell you what. If you can verify that your particular. You have an arm system. With enough distance. And you can verify that LLVM works. Maybe just compile LLVM and all that. We'll be happy to. Processing model. Fixed Julia to make it work on. Using which we have gone and done. So, target it. Okay. So, whatever that. And trim extraction and so on. Some parts of the code is not. Obviously, it's not in GitHub. That's the specific. I think it's installed. Right. And then this gives you the details around the code in the sentiment. And then you can do the things. Details. And stuff. And then you can go to. The specific review and see the content. And so on. Interesting. So, the whole content really is. So, for a user who's looking at it without having to read. The intent. Get a quick summary of. What users. I generally found the feature by feature useless. Because I don't know. Which is the most interesting feature. Yeah. What is it that I should be paying attention to. Especially by machine. So, this is cool. Well, not. No, he was interested in what we're doing with NLP. And. Okay. So, I happened to have this. Okay. I was in the. AB buckets. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. This top and I was talking. I. It's like something. This. This. 1. Why. By. I'm. Doing manually. Up. Buzes. So what is our. Maybe. Maybe a few moments, I think a couple more guys. Will come through. Yeah. So, man, we couldn't. That's right. That's what I think you need to go to the. Yeah let me try. It's working on mine so I must have done something like that. No but don't, I think we should move on if it is. Well we are waiting we can try. The fact that it was able to pull those packages was good right. So it did actually did a git pull. Yeah it pulled everything on all the dependencies. So for all Winston so when I when I said package add. So it did a... So it got Winston, TK, Color, Induction card. Right so all these were... These are repos, repos were GitHub repos sir. These are all GitHub yeah. Okay. You just have to go into the master of each one of these and maybe it will work. So basically what happens is that older version is registered with the metadata. Oh okay. And this is like literally of the you know current development. So wouldn't just a git pull do it? No git pull but it still has to be on the master. Otherwise it will pull the current one. Oh the one with the tag is it? Yeah. Okay. So you said you always... You have the Shah... So it's usually checked out with that version so that that's what gets loaded. So if you just a git check out master. You can even submit patches back to it and use it and you know all that stuff. So now having done that how did you start your Julia? Where is it? The app. So what do you do with Julia? I think... I hear you. You can obviously use it instantly. Do any better. No this was only TKA. See I have the same mountain lion but I don't know why it's hit me out on this. Let me try some stunts. I think there is a... This is chest lion. Oh. Oh mountain lion doesn't have TKA I think. Make any class. Sure. Yeah. I think everyone is getting the pops. I was waiting while everyone is installing. Okay who else is now far away from installation? Yours is working. Julia is working. No. It's installing that. It's still installing PCI-V. Oh it's done is it? Yeah. You can start a JavaScript. Okay. What if you do pjg.iv just... Okay that's fine. Okay. Okay try installing calendar that we are hopefully an easy one to install. Especially on... I think Mac and Linux maybe not on Windows. I mean like... It runs RL... Huh? It runs RL command on Windows. Which one? Then I don't package that. Okay. That doesn't work. I mean like I think I don't design it for you know... OS X and Windows 7. Yeah. Windows is usually less developed. Yeah. From the first thing it gets on as it does. And then it goes to there. Will you file this? Will you file this as a work on... On Windows? Sure. Yeah. But I only get... Capital. pj. This is the exact... This is the... I mean... So UTF 16 there is a user defined... Yeah. Yeah. It's a package actually. It should actually... That... Like a comma right? You can do... You can write like big numbers like that. There are places where you can use underscore as a ignore. So you like multiple... Then you put an underscore. Yeah. That's... I mean the... You know ASCII does not have enough characters for doing everything you want. No. No. No. Just... Because we use the same character for the different meanings everywhere. So... Look I didn't do anything for this one. Okay. Calendar installs. It's okay. Okay. So can we try out some calendars? Yeah. Calendar not today. Okay. So I try calendar not today. Yeah. Calendar not now maybe. Okay. So calendar. And then you can try out these things from the calendar. So the basic takeaway is... How to install them. How to discover stuff inside them. How to install package. That should... Okay. So are all of them functions or are there some other types of... Some of them are like... You know Sundays as they all just would be types. A day is probably a function. You know now is a function. So try calendar not now. It should give you the current day and time and stuff like that. One... Now... So if you do calendar not now. Do type of... So just like see. So you can type of on anything that comes out from Julia and see the type of the object. Okay. So this is object calendar time. Of type calendar time. Calendar time itself probably contains UTF string and stuff like that. Okay. So out of calendar world and out of package world. Let's try the usual simplest thing that I first try is create a new variable. Oh shit. Okay. Try equals one. A plus one. All that obvious stuff will work. Try multiplication. Try some... Okay. It works. Okay. So you know just... What if you now do... I'll just sort of do... Okay. Yeah. So this is rational. So 1 over 2. You know instead of evaluating it to 0.5 you can get a rational number. Again you don't know what the type is. You always keep looking at the types. So what it says is a rational number of type in 64. So these two are in 64. Okay. I tried something else. There is a dynamic reassignment of variable types happening. So I said equal to 1 and then I assigned it to a string. Yeah. You can do that. You can do that. Yeah. You can do... If you really trick the hell out of the compiler and so that it can't figure out the type in its code. You will get bad performance. Okay. So for the most part it should work. So the variables... So there's this... It's almost like a JavaScript. Yeah. Yeah. So you don't say what the type of the variable is. You always do assignment. Correct. So then I try to do some... I mean I try to do an integer operation of that. Then it fails. Exactly. Yeah. So that is not available. That's the string. Correct. Correct. There's even a type for module. Okay. So I did type of calendar. Yeah. Because calendar is the module. Yeah. So... This is a rational thing. This is 1 over 2 like the fraction. That's right. Rational. Yeah. Like rational numbers. Yeah. Rational numbers. There's a package for continued fractions also. So if you really want to get into that stuff. But... So just... This is a syntax. There's a backslash... Backslash gives you rational. So it's just... And brace there means tuple. Where? Rational brace. That's just the... Okay. The good question. That's the way we put... This is what we call a parametric type. So the rational... It's a rational number. But rational numbers can be of... Type int 32 or type int 8. Reserve type int 64. And the reason is int 64 is if you type int on your computer. It will tell you if you're a 64 bit machine. And with the 64 bit Julia it will give you int 64. That means the native integer type is int 64. And usually when you write code you always say int. And it will sort of use the native int on your machine. Okay. So parametric types. The manual has good explanation for parametric types. But let me get into more sort of detailed examples of these things as we go along. Imagine creating any data structure. Let's say you create a tree. Now all your trees are usually looking the same. You will have some left and the right and some children and your parent functions and grandchildren functions and so on and so forth. What will... But the type of every node in the tree could be anything. So you don't want to write a new tree type when you have a tree of integers or a new tree type when you have a tree of your user defined data type which may be let's say stock prices or something. I'm just taking an arbitrary example. So what you do is you typically write your data structures in a generic way. So you have generic algorithms. And then specialize them during when you actually run the code with a specific type. Okay. Let's try random numbers are my all time favorites. So Rand will give you a random number. It should just work for you guys. Now what is it? If you want a random integer. So Rand brackets int. So if you say that the first argument of type int will get a random integer. Will you find this or something? Maybe when I type here something, I move. So random int 64, you know, I get interestingly enough Julia has built in 128 bit rands. And it is just as well in case you need to use it. And it's like providing a seed to that. Which one? This is saying I want an int 128 random integer. So my random integer type is 128 bit. For example, if I say int 16, it will be it's not there. Okay. Yeah. We do only 32 and onwards. So with Rand int 32, that means it can be only, you know, between 2 to the minus 2 to the 31 to 2 to the 31. That's the range. So here, if I say type max of int 32 and I say type min. Try type min parentheses int 32 type max. So that it gives you the lowest value of the numeric type and the highest value of the numeric type. I'm spending a lot of time on numbers because this is sort of crucial. It exposes the type system more than anything else. I mean, a lot of, you know, you guys may not actually need to deal with this much detail of. Okay. Let's try some strings, maybe. So the strings are all double-coded. And then you can do, oh, that's a tool. That's not what I wanted. Okay. A star B is the concatenation. Yes. So in Julia, so I just did a quick set of things with strings. I guess it passed by it. But that sort of gives you a feel for strings. The double-codes stick anything in there. And then there's a usual bunch of string operations. What is the difference between the ASCII string there and the one over there? This is an array. So aren't both of them arranged? No. And that's, you know, we should, we'll find out. So if you're a MATLAB user like I was, your habit is to try these kinds of things, but... Okay. So, and I haven't quite thought into arrays yet, but it says it's an array which has strings in it, as opposed to the other one which actually concatenate to strings and give you a new string. No, not this one. The difference between this and A comma B. Okay. A comma B gave you a tool. So you can take any values and stick them in a two-pull. So I can have a two-pull of one, you know, of L, comma, minus four, comma, another two-pull. Basically, the difference between a type list and an untyped list. Yeah, it's an untyped list. It's something that we use to pass arguments and small sort of collections of things back and forth. Do you want to try something? Yes. So as expected, arrays also type parameterized. Yes. So, arrays type parameterized, you can have an array of float 64, array of N32s, so on and so forth. And now, you know, when you implement arrays, right, you often think about... For example, in Fortran, when you have an array of float 64s, array of doubles, they're inside the array itself, right? As opposed to arrays of user-defined types in many cases, often become arrays of pointers to things. In Julia, you have both. If the type that you use is a concrete, immutable type, then you get the layout in your memory. Otherwise, you will get it keep allocated with pointers. It will be... This does not matter to you that much in terms of... As a user, you probably not even know what happened. But performance-wise, it will be a big difference. If your types are immutable and hence the array is just the immutable types laid out in memory one after the other. So think of numbers, right? So float's double precision numbers all one after the other in memory versus a pointer to a double precision number. So, for example, in an early implementation complex numbers, which is a real and an imaginary, some of you may have not done that for a long time. So real and imaginary numbers, we had to go through a hack so that they would be stored in line in memory. Otherwise, every time you access it, you have a pointer and then a pointer to something and then... We have the immutable keyword in Julia, so to specify immutable types. And so you can say immutable something and then, you know, for example. So that, you know, this won't have done much. So everything comes back to... If you type of a type, you get the type data type. So data type is sort of the most fundamental type inside the Julia type system. So to illustrate some of this a little bit more, you know, if you look at the examples that Julia comes with. See if you look at this modern example. Okay, so here's all of you guys familiar with modular arithmetic. It's... Okay, let me just illustrate it with an example. So a number n modulo k is basically the remainder when you divide it by that number. That's the percentage operation basically. So I'm just going to take this code, let's just do it one by one. Can you explain the syntax? I'm going to do that, but as I type, as I go along. So this is an example to describe the type system of Julia and how types are created, how types are annotated. And this is really where the power of Julia comes from when you do generic programming. Import all Bayes. This just says that, you know, import everything from Bayes into my current namespace. And the reason is that, for example, the Bayes namespace provides a number of basic things like, you know, operators like addition and subtraction and multiplication and so on and so forth. And when you overload them, you have to be explicit about importing them from Bayes and overloading them. Otherwise, you know, you end up being unclear about which ones you are modifying the behavior of. So without worrying about it too much, you just usually just import all Bayes and you get everything that is in Bayes. In order to see what is in Bayes, you can say Bayes dot and tan. So all of this is in Bayes. So import all Bayes just brings it all into your namespace. That was a bad idea because it's gone up now. I just put that back on screen because I had already defined it, so it says invalid redefinition. Now what I've done is I've created a type called modend. So that says the name of it. N is the type parameter. And this is going to use the parametric types in a very interesting way. This operation just says that it's a subtype of the integer type. So that basically means that it will inherit a bunch of integer-like properties. And then immutable means, you know, you guys are familiar with the immutable versus, you know, immutable types, right? So the problem is that there came something like this. This is going to be a challenge debugging real-time. Hardware is awesome. Can we plug it directly from the laptop to the projector? No, actually we are doing it. Oh, you are recording it? Yeah, okay. Okay, so this type is immutable. Typically, if you say immutable, then everything gets... The difference between immutable and immutable types is that immutable types are, you know, when you mutate it, it's observed by everyone who is observing it, right? Every other thing that is appointed with a immutable type. So when the immutable type is changed, things are changed, and so you have to be careful about it. When a type is immutable, it gives the compiler a lot more flexibility. So it can be stored more efficiently. And copies can be made. It can be passed efficiently to functions and so on and so forth. There's a beautiful blog entry on the Julia blog on immutable types. So we are going into further these things. I'm going to say that this is an immutable type called modern type parameter and subtype of integer. It contains, you know, this is just like a regular object, right? It contains an element k, which is a regular integer. And then there is modern type, so this is a constructor. So this just says how to create this... Create something of type modern. So the next thing we'll make it much clearer. Okay, so let's first do an example here. A little bit. Less than column sign. That's a modifier on the type parameter or the data type that you're defining. No, it just says that it's a subtype of whatever is on the right-hand side. So the whole data type is subtype of... Yes, yes, so modern n is a subtype of the integer base class. I mean, think of it as an abstract base class kind of. So here I have done, I have created... Here what I've done is, this is a type parameter 5, and this is the value 3 that I've given. So the value k should be mod of 5,3. 3,5. So if I say a equals this and then I say a dot k, you would expect it to be 3. If I now do 10, 10 divided by 5, you know 10 divided by 5 perfectly, so you won't have anything left in the module or the value should be 0. If you say 11, you expect it to be 1. So a dot k is 1. k is also a module. No, k is the base of the... k is the parameter... This thing is almost being too cute in its use of type parameters. So the parameter itself is not fixed, right, unlike a double precision float, which was a type we used... It itself is varying when you construct a new type. I just know syntax, you showed that when... Yeah, this is the third line, where it has modded k. k is our name, but why does it have modded k equal to nu? That's the way we define functions in Julia. So if you have one line function, when you have a... Sorry, it's a good question. I mean, I take these things for granted. That's a one line function definition there. So mod n taking, you know, that input, that's what is done on the constructor, basically. It's a constructor. So what... So here the parameterized type, right? Yeah. So why couldn't it have been... Whatever you're trying to do, you said it's a specialized use of essentially specifying the... So the key comma n could have been specified as part of the constructor itself. Instead, why do you define it as a... What is the benefit you guys get by defining it as a parameterized type? I will show... I'll get into that next as we... So a simpler implementation of this would have been that if I wanted to work with modded file, I could have removed the type parameter n out of here. I could have just had this, and I could have hard-coded the n out here as 5. So then I would get all numbers in mod 5. And then I wouldn't have needed this parameter, right? But then if I... What if I needed a mod 10? Then I would have to create a new type with 10. So what if you did n, you defined it as another integer? It could have done that. It is implicitly an integer, right? If I gave it a... I mean, I can try and trick it, for example. And that won't work most likely. Okay. So mod operation does not work on... So in this particular example, not, but you're right that otherwise I could have tried and... Yeah. I was just trying to understand the benefit of those parameters. Okay. So better way to write this would have been also... Sounds like... ...amplitating people. It is, it is, it is very much... Yeah, you can... Like a person, right? Yeah. Like a different mode of... Correct, correct. So this is the whole idea is to do generic programming, right? So I want to write code that I write once and can be used, reused in multiple cases. So... Think of it in the Julia library, right? We have operations on arrays. Your arrays could contain anything in them. So, so long as, you know, there are numbers, and you say plus, it will do plus. But imagine what if you didn't have a plus defined... So that's exactly where we are going to go now. Okay. So we created a few modules. I'm going to define these show methods first, because I don't want to type this... Examples have come from the source, right? Not from the devian package we installed. They are... But the examples directly should be included. Okay. Yeah. It should be included. Otherwise you can just clone it from the... It did happen... So here's the... Here's a show method that I'm defining on this type just to show it in a nicer way. Okay. So it just says what's the, you know, what stream to use for IOS. Right? So almost sort of boilerplate, you can think of the first part. And this is the input. So here we are beginning to already see... Okay. We are beginning to see things like... What in Julia is called multiple dispatch? The same function defines all different input types can have different behavior. Kind of, you know, in polymorphism. But based on type. So when I have the show methods, every object in Julia has a show method that can be defined on it by these users. And its behavior can be changed based on the input type. So if I have a show method on calendar time, I would like to print it like a time object, you know, like print it as a month, year, you know, day or so on and so forth. A show method on a mod in... Might want to print X mod Y. A show method on anything else. So you can overload the show method for your type using multiple dispatch... This is not an example of multiple dispatch. This is only single dispatch here, but let me make my point by doing the example here first. Ah, ah, ah, good point. This should have shown it. I don't know what I've done wrong here. One second. They would have expected it to do this. So some reason this is not picking up. That's fine. So the show method, I mean I... Apologies, this should have been picked up directly when I print in the value of A itself. But it's not happening here. But this is how I wanted to print. Okay, now I go in and I define the behaviors. This is just, okay. I've just pasted that in the REPL, but I'm just going to explain it right here. So I say now that I have integers of type modded, I have defined how to print them using the show method. I've defined, you know, how the behavior works. Now we define how the operators of them work. How do you add two numbers of type modded? They don't, you know, because they are modulo... Modular arithmetic, this is how they work. And so basically what you do is you take the stored integer of the first, you know... So if it's A and B that you're adding, you take A dot K, B dot K, which was the stored value inside. You add them and then you do the modulo operation. And the modulo operation is done by you calling the constructor on the result. Okay, so we defined four arithmetic types. So let's try it out. So let's say I had A, I could have done... Now if I do A plus A, I get... If I do A times 5, that... It didn't like that. And it didn't like that because I haven't defined these things. So I'll come to that next. If you do A minus A, 0. Okay, so that's... Until we have defined these operators here. These operators that work on these different types. Now typically what's going to happen is when you do a plus, your system will have definition of a plus for your base types. Did you know how to add numbers or how to... Maybe plus is overloaded for strings. Maybe plus is overloaded for a number of other types. But obviously modulo was something you defined. So if you gave two models to your system, it would have absolutely had no idea what to do with it, which is why I had to define this behavior. And this is what we call multiple dispatch. So the same function, plus... He has differently based on the input types. You don't have to call it plus. You know, modded plus as the function name and then sort of use horrible operator names. You get to use the same syntax, the same operators, but dispatched on the types. What is that n doing after plus? Where? So in the plus definition, brace and brace, is that again... Yeah, so anything that is a type parameter, you have to put it up here to say that these things are type parameters. If you don't, it will just think it's part of the... So here it says it's a type parameter n. So it means that this n and this n are the same. So the compiler now knows that it takes input of these two types and output also has to be of the same type. So all type parameters come up in the function definition. And we can pass multiple by... Yeah. And you can even put constraints on them. So just like you put the subtype, less than colon, you can say that this n here should be only of type integer and so on and so forth. And our last two things here are convert and promote tool. So this is underlined type machinery, which kind of gives the system hints of how do I work with two numbers if I get a mixture of things, right? First one says how to convert a type model to an int. That's why it's the other way around. Convert an int to a model. So it just says that if I see a mixture of operations of ints and mod ints, then I need to convert one to the other. What do I do? So it says... Yeah, just call the constructor on it. It's going to happen implicitly. Yeah. Once I define this, it will happen implicitly. So convert is then something that you do instead. Yes. It's the underline... The machinery can call it. And the other one says promote tool. So it says if you see operations involving a mod int and an int, mod int wins. So if I see mod int plus int, it will become, you know, promote int to a mod int and then add them up. So I have not yet defined these, I believe, the convert and the... So if I say a plus one, it should not work. And it will probably get the... It's going into a stack overflow right now because of the same... It does not know what to do. Why does it go to stack overflow? Should it throw like a... Yes. All crashes are bugs and need to be fixed. These ones are, you know, things that sort of go recursively and sort of blow the stack are very difficult to fix. I mean, to catch and prevent. But, I mean, as soon as I go back, this is going to be filed as an issue. Okay. So now I have to just redefine all these things here. So I'm just going to define this whole thing now. Okay. So if I say mod int of 5, plus one, back then it could not... It did not know what to do. So it was just kind of trying to figure out and, you know, the real answer was that it did not know. We had not told the system that I have a new user defined type. I had told it the behavior of plus, but I had not told it what to do when you see a new integer type. So you... So this is... But in this version now, I have defined these conversion and promotion rules. So it now says, okay, I will convert the one to a mod int and then add it, calling the plus function. So this is really like, you know, all the basic arithmetic of Julia, all the basic, you know, inbuilt stuff, a lot of this is implemented in the language itself because of this level of flexibility that the type system provides. Now let me give an example of arrays, right? Let's say I want to do a... You know, I've already shown you the random stuff, but let's say a 3 by 3 random matrix, right? This is... Let's just get... And does this work? I had said int 32, whereas I'm working with int 64 right now. So bad idea to ever specify the precision. Never do it when you can avoid it. So this... Okay, so here what I've done is... This is how we create a 3 by 3 array. And if I put a random int in front of it, you get a random array of integers. What I wanted is a random array of mod ints. Not regular ints, but mod ints. Since I've defined this convert method for one int to a mod int, you know, the machinery works when I say that convert this matrix to a matrix of mod ints. So now I've got a 3 by 3 mod int 5 array. Now mod int 5, if you remember, you define it as an imutable type. So these are actually stored continuously in memory in a highly compact fashion. You know, it's not... This is a capability that we've got recently. So imagine you have a very large array of these things. It would start becoming very slow if you didn't have imutable types. So just with these 10 lines in user-defined port, you've got to a capability of something like this which otherwise would have required creating a ton of machinery in many other languages. Are you still using the heap? All objects and heap allocates anyway. So it doesn't. But it would be a heap-allocated array of pointers, too. And then each one would be a little too big. If this was not imutable, you would have had an array of pointers. And each pointer would be to a mod int object which may be taking up 16 bytes or 64 bytes. And then little allocations all over the place. So for each iteration, you would have to keep a dereferencing. Correct. And the cost of garbage collection that just keeps blowing up. So I say, you know... And now here's the kicker, right? So if I say A plus 1. Notice that I have not defined anywhere what to do when you see an array of models in my entire definition. I'm just using the 10 lines of port which says how to create models from integers. It says how to convert models to integers and back. And it says what operations you can do with models. And it shows how to print models. The print is not working right now, as you keep that aside. Now, you could imagine that the array code probably says that if you see an array of... If you see A plus B, what to do, right? Take everything inside array 1, and inside array 2, add it and create a final output. But I never told it what to do with array of models. The generic array implementation, when it was told that if you get a model, if you have a definition of something called a model and as long as the plus method is defined, the compiler was able to piece it all together and add one, two and array of models here. Without me even saying. So this is the power of generic programming. So you could have created an array of your own objects, overrode your own operators and get all the array operations for free without actually writing it. And this is not just... I mean, I'm just using arrays, right? I could have done this example with a dictionary, for example. So I could have stuck these numbers into a dictionary and then done dictionary-style operations. I could have created a set. I could have created a tree, for example. So dictionaries and sets are part of... trees are not yet... So here, interesting thing is that the modern type interpretation seems to happen post increment. So if you see the 4, the value becomes 0. Correct, because it's more than 5, yeah. So we have said the way to add these numbers is you take this 4 and then when I say plus 1, promote 1 to a model. Okay. Then it will add those to 4 plus 1, 5. And then 5 divided by 5 leaves no remainder, so 0. So actually the plus 1 that 1 got implicitly converted to a model, right? No, because of our definition, right? I had defined... This was the definition I gave it. If you look at example, this is how plus 1 mod n works. This is if I get a and d as mod n's, take a dot k, a dot k is just an integer, right? That's an integer inside the modern type, like this one, right here. So it says take a dot k, b dot k, add them and then promote them to n. And then the conversion rule is as follows, the promotion rule is as follows. Correct. So I meant that. So before plus is applied, does it implicit? Yes, yes. Upgradation and whatever. Correct, correct. From one to one into one. Correct. But what I meant is implicit isn't the... Julia did not make the decision for you. You have given it that decision in the promo rule. Okay. But once you call the promo rule, it implicitly applies it when you did. So this entire machinery is in play when I did a plus 1. And you are getting the performance as if you had handwritten a C code to do this operation, specialized to this time. In your real uses of Julia, do you ever get into the combinatorial explosion of promo rules? Do you get such scenarios? There are, I mean, not in the real... I mean, not an explosion that kills you while you are doing regular stuff. But people who go about creating... Could be very complicated. Artificial explosions. And the promo rule can take only two... Yeah, and then, I mean, it's because an expression will then get implicitly applied, right? A plus B plus C will do the promo rule of A plus B, then on the result, you will do the result plus C. I'm curious, what is the motivation? Which scenario did you see that allowed? Like, so whenever you have a rule sort of scenario, right, there is always a chance that... That's what I'm saying, general sanity check. General, yeah. So the question is basically like, do you get these things in real life? Yeah, in your real... Although theoretically it's very much possible. There are a lot of heuristics that Jeff has put in the compiler to avoid such explosions also. And the heuristics kind of work well in real life and unfortunately I don't know them very well. We can dive into the compiler to take a look. Okay, so... So now, this is the kicker of the lot. So A times A is matrix multiplication. So matrix multiplication is typically a three nested form, right? Everyone here remembers the matrix multiplication, right? Maybe. Maybe. But it is a non-trivial operation. That's all I know. So somewhere in the guts of the array implementation is probably a triple nested. Actually the reality is not the trivial implementation that Julia has but a highly sophisticated implementation that worries about cache and locality and placement, which is more code that you'd like to read. In fact, we never want to read these codes. But I did not say anything here. I just said A star A and I multiplied an array of mordants with a matrix of mordants and other matrix of mordants. But if you recollect back to your matrix multiplication, the only two definitions it needs are how to multiply two numbers and how to add two numbers. So if I have two things, I say this times this plus this times this plus this times this, right? If I had a byte mode, I could have put it there. So it just really needs a definition of star and definition of plus, which we have provided in the rules that we said how to add two mordants or to multiply two mordants. So when the matrix multiplication was happening, it said, oh, I'm multiplying an array of mordants with an array of mordants. Now, inside that, I have to take the first row and the first column. And that I have to do a dot product. It would end up being 2 times 2 plus 0 times 1 plus 3 times 4, but in modern arithmetic. And then calculate the output, calculate the answer, promote it to modern and store it back. So it did all of that with the very concise set of rules that we had given. So it is an academic thing. I mean, whoever works in modern, maybe some mathematicians somewhere might be. But I mean, this example has been artificially constructed to sort of illustrate the power of the type system of Julia. And now, instead of modern 5, you could have just changed this example and make it modern, you know, 1 million, 2056. And it will just go on. You don't need to rewrite the code or you just instantiate your code with a new n-parameter and you are put to go. So this is a good example to play with and add one more thing, you know, multiple. What do you think? This would work now. That's a good question, right? It should work. It should work, right? So yes, it will work. What about this one now? This is a good one to try. I am taking a modern array which is A and I am taking a regular array which is this. Any guesses? It will. The answer I don't really know. I am just going to try this out. It feels like it should work. Because if you think through it, we have defined all the things that it needs underneath it. The key thing here is the promotion rule is coming into play every time. If you do this on very large arrays, you will start seeing differences in performance between this one where both are moderns, whereas this one where everything is being constantly promoted. And then you will find that if you go manual promote and then do it, it will actually be as fast as the other one and so on and so forth. So you can sort of, your performance can greatly vary depending on the order of which you do things or if you have too much magic happening underneath your code. Usually this much magic never happens in a user's code. You will never use all of this in one program, right? You will most likely be using some parts of all this machinery in stuff that you do. Okay, so this is one example on modern. I don't think any, I want to look at any of these other examples. So convert is a keyword, right, in that case. Convert function is a keyword. It's almost, it's not really a keyword, it's a function. It's a regular function, but it's sort of a function with special meaning inside the system. Can you just go to the previous examples? Not that, like in the terminal. Okay. So in the deadliest one, right? 2 by 2, 2 by 2 is 0 or 5? It's 0, right? So the top A is 4, so 4 plus 1 is 5. Right. So that is giving 0. Because it's modular, right? So you do 4 plus 5, then divide by 5, take a remainder. That's the mod. So here, right? Mod 5 comma 5. That's the answer. So similarly, I just wrote a simple package for doing, you know, you can go crazier than this. You can change the meaning of what happens inside a matrix multiplication by saying, so the common kind of algebra is max plus algebra, where instead of multiplying and plus, you do plus and max, max and plus. I don't get into, you know, why you need to do that blah, blah, blah, system, queue, theoretical stuff. But the point is, the language is so easy enough that you can pretty much go about changing a lot of the inbuilt meanings of things to suit your needs. And hence, remove the need for writing a C program. If you imagine writing a C program, it actually is going to be quite poor performing in many cases. Because, you know, you won't get this level of generic programming and inference and code generation. Wouldn't it like, I mean, you could be as explicit in C plus plus, but if you use templates and if you overwrite it... If you use templates and operators, you should get pretty close. I think all of that should be possible. You should be able to overwrite... You still won't get multiple dispatches. Multiple dispatches there? In C? In C plus plus. Multiple dispatches. I mean, if you, in late binding, you would have to define, like, some kind of interfaces. You wouldn't have an interface in C plus plus, but you would have to use virtual functions and dispatch from there. So, I mean, the point is nothing in Julia is that new, right? All of what I just showed you. It's a combination of programming language techniques that have existed in a number of languages that have been put together, you know, for the purposes of these kinds of computations. So, you know, multiple dispatches is not new. You know, operator overloading is not new. But some of the things are, you know, nice, like the way we did the plus operator, you just said plus and t comma b, and you could just write, you know, the function definition in a line, you know, sort of shorthand and easier to read kind of stuff. So, that may be a new, I don't think I've seen that, but I'm sure that someone will say that it was there in some other place as well, so on. Now, I'm using Pamela's, which is based on one pie and so on. Okay. You can do a bunch of these things. Yeah. Okay, so this was sort of, you know, the main thing I wanted to get across in this thing that, you know, the whole thing behind everything is this type, inference, type promotion stuff, but I'm happy to sort of explore a few other things now, depending on interest and, you know, if I'm able to actually use those things on the fly. Someone had asked for a parallel use case, right? You had asked for about parallel stuff. Let me just quickly point you to the manual, to the example, and you can probably even try it out. So, if you want to start Julia with multiple processes, I mean, I have only two, so I can only do this. It's very similar to Nick. Yeah. Yeah. So I do this. I say n procs. I get two. I can on the fly also add more, but it still worked. Yeah. Yeah, it can go distributed. So on the command line, you can give it a list of machines and then SSH there and start a Julia of there and so on and so forth. So what's happening? It's created three Julia processes. It's just started. I mean, it's not that magical actually. You can just see. How do you send commands? You can open variables? Yes, yes, I think so. How do you send instructions to all these separate processes? I'll just get to that, yeah. So, you know, you've seen that the other guys have been just started with a different set of options. You know, some, it says what to bind to and how to communicate back and just set up all the PCP connections. Is it using shared memory? No, I think it's not using it right now. We have plans to use it. We have plans to use Schmem. So that you don't have to copy stuff and transfer it, but not right now. So if you want to do like a matrix multiplication with three processes, it creates a copy of... It won't work because you have to overload the hell out of everything and implement lots of copying and stuff. But when you're the shared memory one working, you will get something like a matrix multiplier working. That said, implementing a parallel matrix multiplies only probably 10 lines of code. The right 10 lines. I mean, setting up everything. Okay, so we'll just try a few parallel and distributed code examples. So Julia, this is readthedocs.org for his documentation. He's not as familiar if you use GitHub. So every time GitHub, there's a commit it can push off the latest version of the documentation to the online version and push it out. So there's a chapter on... Actually, a couple of things I want to show is... So we talked about arrays. I want to show parallel computing and then we'll look at how to call C code because I think that's probably going to be of general use to everyone here. So I'm just going to kind of jump to these examples right here. So this syntax is pretty straightforward. It says remote call to processor number two. This is the function that I want to call on it. These are the arguments. I should not have done that, I guess. This was the one without the procs. So I'll just add two processors. Okay, so I got all of them now. So every time you do a remote call, all you get back is a remote reference. So it says I sent something over the network to some processor and it did something and it just gave me a reference to that thing. I can look at it by saying fetch. But if I'm an impatient kind of guy, I can probably do this. So I can do remote call. I may just spawn off a bunch of stuff and not care about it. Or I may just be impatient and... Sorry about this, what's happened here? Just close all these. Okay. So fetch are... And you have syntax like this also to do the same thing. So you can spawn threads on another processor and have it go compute and send back a remote ref. So as you can imagine, this is like absolutely low level but capability but you can pretty much do anything with this. I mean it's a remote procedure call. I can run a function, load it anywhere, all that stuff. So let's say when you're doing this and you find, you expect or you experience errors and things don't work. You're in terms of debugging. It's very difficult. Yeah, so currently... The parallel support is relatively new. So one thing is for example, there may be an exception on a remote node or a remote node dies and it won't even get trapped. But those are things we know how to fix. But debugging distributed code is very difficult. Some of the things you're planning to do is to just make it easy to attach a debugger to a... Let's say if you don't have a debugger but the call is not going to the remote. What do you get to debug? Currently you're on your... You get printf, that's all we have. So you may have printf? Yeah, you can stick printf wherever you want. Maybe you shouldn't start the process and if I try to do the remote rep I was wondering what would have happened. We can just try that out. So I'll do this. This is probably going to take some time before it figures out. In this case you haven't created two processes. Exactly, that was the question. So you haven't created what are my tools for knowing. So ideally when you write code like this you should never write it in terms of processor addresses. Sure, I think this was probably a bad example for you never address it by processor. So this was simple. But our plan is to go towards having non-addressed types of distributed... You know, creating process groups and then addressing process groups and so on and so forth. I mean, Erlang does a lot of this stuff quite well actually. So we may end up copying some of those things. But for the time being this is what we have... I guess this is probably going to do nothing. Sure. I'm just curious to know how does the multi-process design implement it because we discussed having open LPs not support it. It's just your pure TCP IP. Internally uses Pthreads. No Pthreads. It's just TCP IP. It's just myself passing. Buckets and serialized. Correct. Sockets and every... So native Julia types can be serialized. Any native Julia type that you give it, composite type also it will serialize it and send it over automatically. So I believe it must be using MPI behind the scenes. No, it doesn't. It just uses TCP IP. It's like... It's simpler than every of the other alternate as you mentioned. It's... Okay. It comes with the one which is some... Package. So this is... He knows more about networking than I do. He should be talking about it. I'll be talking about HBC and... Yeah, it just does absolutely simple stuff and then... You know, that goal is to do very simple things and make them very robust rather than doing something very sophisticated and complex and having it difficult to debug like this kind of stuff right here. Okay, what do we do next? There are some other nice examples here. I want to do that parallel one. Guys, I'm going to write this function here. Okay, and I'm probably... Just one more question. Yeah. Sure, sure. There's this trend actually going on of using dedicated hardware accelerators like DSPs or... Correct. And computer intensive apps like Matrix Conservation all are actually perfectly mapped on GPU hardware. Right. So does... There are... There are frameworks like QDA and OpenCL. There are people who are sort of linking OpenCL and QDA to Julia. It's not part of the Julia core and probably will not be for a long time because we will not be generating code for GPUs and such. That's pretty difficult and... We have a lot of other stuff to do before we get there. But for common kernels like Matrix Multiplier and all... Yes, yes. So there already are people who are linked up libraries. I don't think anything is actively maintained as of now. There's a bunch of work that has been done. A lot of the times in real life, for general purpose programs, you don't see that much of a performance gain unless you have a very specific application because of the memory hierarchies and so on and so forth. So there are specific classes of applications where you see great performance, in which case what I would suggest is to write that part, you know, anyways as an OpenCL library and call it using our C interface. Not my style, preferred style of programming, but if the performance is worth it, go for it. Okay. You want to break the tie in Samosa? Should we? Yeah, let's do that before we jump into this one. Yeah. There's some tie in Samosa upstairs. You can do some parallel examples post snacks. Now, I was here for the video source actually, so we have made for you all.