 So because I have few content on the basics of the function programming, basics of syntax of lm, so I'm just figuring out whether to cover that or skip that. Skip? OK, right. And do you want to see a demo or do you want to see a live coding? Like, I just want to know. I plan for do some kind of a live coding. Is that fine? OK, fine. All right. So my name is Jaram, and I started doing some kind of function programming maybe three or four years back. Now I work with my teams to adopt some of these practices, so that's in short. Long one is in the slide. All right. So typical of UI development, how many of you faced probably a choice to make some decisions or made some of these errors? All right. So even recently, probably a month back, we did what is on the right-hand side. In work, we chose React as a JavaScript framework. So it happens all the time. So in that context, let's peek into lm, and the focus is on the architecture, so I'm not be covering many of the functionalities or syntax and other things, so mainly about the core, the heart of it. What is lm architecture with respect to UI development? So the prerequisites, I want to do a recap, which I'll skip now, so it was the basics of the functional programming, which I'll skip and directly go into the lm part. So I'm just going to skip all these things. So you're aware of all map, flat map, filter, fold, partial application. Fine, I'll skip all these things. So let's bring this into lm. So I'll start talking about some of the literals, like how you do. I think there are four of you who have already done lms for the rest of all of us. So it's about defining values. You can see that it's in how do you define an int, care, string, bool. So essentially, it's for the format. You have a name and a type. So if you have seen previous sessions, Haskell double colon, so it's a single or, I don't know, Haskell or something else, the name equals value. So that's the defining, type signature, and the actual value. And so these are literals. What do you do when you go for functions? It's not something, it's actually the same. So there's no difference between how do you define a literal versus how do you define a function. So this is an example. So you have an ad which takes two parameters and returns a third one. So it's the same as defining values. But I said that it takes two parameters. I mean, typically, if you see it is, so add one and three of the parameters, which is not true. All functions take one parameter. So here is the example. So it's an ad. It takes one parameter, first integer, which returns your function, which takes another integer, which returns an integer. And if you pass two, then you get the final one. So this is all functions take single parameter. It's same as carrying. And of course, how do you invoke? It's by white space. There's no parentheses, so add one, space three. So that's all invoke functions. And of course, records. So you can create custom records. You can give a name for it. If you don't want to give a name, you have to always use that structure within the curly braces every time. So it's a good idea to give a name, give an alias. And you can define your own type. So it's called union types, or in which, let's say in this case, it's a, your type is music. So it's vocals, or acoustic, or other. And string, you see the string is a type parameter. That means other, which holds a string. All right. There are certain other things when you talk, when you read about Elm or Watsmer, go to the tutorial and other things, like strong static type checks, or probably pure JavaScript developers, it's a cool thing. But for others, it probably is not. It's most of the other programming language that does it, other statically type languages. And another important thing is the module version dependencies. For example, if you're using a third party module, and they release a newer version, and there's a impacting change, or back, if they make a change which breaks the backward compatibility, Elm will force them to upgrade the major version. So you are guaranteed that if you declare dependencies in your Elm package or JSON, it's going to work. You are not going to have a cross-version dependency issues. And finally, the debugger in the Elm, or in which, literally you can go and replay all the events to the lifecycle of your app, and then see. So you can go back and then see today's talk, Brandhunter. So he showed that Mario. Yeah, it's the same thing. So this is a quick check on Elm. So it's like basic intro to sync talk, so that you are going to see some code. So at least you can read the code. So that's the objective of just introducing this very quickly. So this is the code part of the session, and there's only one slide that I have, and that's what it is. There are other slides, but this is what it is about. So this is about model, view, no controller, it's update. And here the view is a function. Update is a function. Model is a record, or struct, or thinking about object-oriented class. Probably would not use the word class. It's a record. So we have a model. So this encapsulates all the data that your application or your web page needs. And of course, it's a view. Like this is the representation of the data. So how do you represent that? And there is an update function. So the green ones are the functions. And of course, you have a user. You have an external world. You have a browser, which does something, like all the external world and users are using the system. They are interacting with it. The first step is that generates a message. And the existing model. So this message and the model becomes an input to update function. So what update function is supposed to do it? Take a message, take the current model, and give a new model along with a command to the runtime. So this could be something like somebody clicked on something, somebody clicked on a button. So that generates the first message. And it takes the current, runtime takes the current model, pass it on to update function. It generates a new model, which could be same as before, or it could be some changes based on what it is supposed to do and generate some command. And this command in turn gets executed, can generate another message. That cycle continues. Is it clear till now? Ultimately, the elm runtime will use the model. I'll come to that on how. Even to call the update function, elm runtime will pick the model and then pick the message and call. But from a logical point of view, it's like update function takes model as an input. Let's not worry about who passes it at this point in time. So now we didn't talk about the model on the right-hand side, the one which update function generated. So that gets passed on to the view. And view sends a HTML data along which can send some messages to the runtime. So what this HTML message means is probably it's a bunch of HTML content or the DOM structure which can send messages to update. For example, what happens if somebody types in a text box, somebody clicks a button, somebody selects a drop-down, all those are messages that is coming into. We'll see that in the code. So this is an elm runtime who actually receives all these things and orchestrates the entire stuff. And of course, the application developer, what you focus on your view, model, and update. So we have model as a record. Message is generally other types, like you define your types, and update is a function, and view is a function. So update takes in a message, takes in a model, gives you back a new model, and a command message. And view takes in a model, and gives you back an HTML content. Oh, no, that's generated with the view. So I just, view is green, so I made that green. That's all there is to know that. Command message. So it's like, let's say, OK, you click on a button. I'll tell you the extra use keys that you're going to see now. You click on a button. Let's say it's to post a message. Now you want to invoke an API as part of that, and that invocation, and get the response, and update the view at some point of time in future. So what you tell elm runtime is, run this command. And the command will tell what is the HTTP method, what is the URL, how do you handle the response, like what is the decoder, like if you respond to JSON, how to decode into your special records, and all those kinds of things. It has instruction. It doesn't do anything. It doesn't actually make the API call. That runtime does it. But in certain scenarios, there may not be any API. For example, it's just a dropdown selection. You just want to show, reflect the selection in the UI. Then there is no command. So command is, depending on what action user is performing. So we'll see that in an example. Update is every, so here on the right-hand side, everything is a pure function. So pure function means you cannot have any side effects. So if you invoke an API in update, you're changing the world. You're changing something outside the website world. That's your causing a side effect. And you cannot, OK, yeah. There are other things, testability, and all those factors. This is fine. This is the whole purpose of this talk. It's just one single slide. Let's for all demo and code and other things. So can I move on? Cool. So let's, I'm hoping that the network, everything is fine. So let's get our hands dirty. So we'll go through what we are going to build. So there is a service running which I'm going to use, which allows for somebody to connect to it and send messages to other users who are connected to the same service. It's just a dummy demo. Not dummy, the real service, but just a demo service. And I only have an app which actually purposely built for this purpose so that it doesn't allow you to send it. It shows only, it connects and it only shows you the messages you got. You can't send it to anybody. For this purpose, let's assume that I'm going to build another page which allows only sending. I don't want to combine at this point. I'll do that later after this. So to separate it out, I have something which receives the message and displays it. So we are going to build something using which you want to send it. So now how that is, let's take a very simple case. So I specify a user ID. Then I want to type the message which I want to send. And I'll click on Send. This has four aspects to it, four parts to it. One is the recipient, whom I am sending the message. Other one is the actual message. It's what I need to send. And send button or an action that user needs to take. And this part is where I want to show the status, like sending the message or send fail or send successful, blah, blah, blah, any kind of status information that you want to show to the user. So this is what we need to build. So let's do it. So I'll mirror it. You can see that. That's pretty readable. Reduce a bit because this is fine. So three things. Model, view, update. So that's all we are focusing on. So let's go to, OK, before that I just want to show you. So I'm going to connect. This is the app which just connects and receives, and displays the messages that are received. Let me connect it to myself. So I don't have any message now. I just connected, displayed. All right, so now let's see the model. So we have, OK, first we'll see the messages that are applicable here. The way to think about the first thing is the very straightforward thing is notify. That means if I click on send button, it has to do something, so that's a one message. The other things which will become clear as you start doing this is if user types are recipient, in typical way what we do is, OK, I feel something, the element dot, blah, dot value, in JavaScript we get that. So here everything happens as messages. So as I type on the recipient field, or as I type on the message field, it has to send a message to the run time and send a message to the update function. So I need to have types for those fields. So let me call it as recipient, I think it's called ready, and message ready. So this covers recipient, message, send button. We had one more thing which showed the status. Notify, notify successful. So let's call it as status, let's call it as status. Status may or may not be there, because initially there's no status. Only when user is performing some actions it is. So how do you do that is maybe status. So it may be nothing, or it may have some value. So that's nice. So I have one error, sorry, sorry, sorry, not here. That's all it is, confused with the model. So next is the model. So model, it's already pre-populated. The recipient and the message is pre-populated. So here we need to add status is maybe string. I may have a string. And there is something which is very peculiar about, or peculiar, the syntax of the API is that. So this is actually API that we are going to call. So I'll just show you. So this needs a message and a sender. Who is sending this message? So we'll have a sender as well as string. So we completed our message as well as the model. So notifyResponse body, so we have to see. So notifyResponse here it gives you a status as well as the string. So let me add that over here. So it's called client ID call and string. So we are completing this. So now here you get, I just wanted to show you all this compiler errors and all those kind of things. So here you see that it looks like a function definition. It gives a message. Essentially the problem here it is, this is decoding only one field. So we need to add another field over here. Field, client ID, JSON dot, decode dot string. That should go away. And I have to use map2. This is gone. So now I have defined most of the stuff that I need in my message and model. And I have my updateView function and update function. Update doesn't do anything right now. So view is just doing some to-do note. So you see the error over here. That's because our model has changed and we have not updated it. Now the model has four parameters. So I need to say that the third one is nothing and fourth one is a string. So now we are all set. So now let's see what happens. So we'll go here. So you can do a, well, let me run the reactor. So we'll see how it looks like now. OK, it has only to do nothing else. So we can actually see here that this is our model. We have everything empty. There is nothing over here. So we will continue to add the view part now. So you go here, view, let me save some time and copy it. All right. So there are some helper functions defined elsewhere. So I still have one error. Yeah, so that's attributes. Still there is one recipient ready. All right, these are good messages. So do you see an error? I want to show the linter. It's here. So what it says is, text input is expecting a string to message and message. So now you see here, when somebody types in something to test, we have told Elm that recipient ready, in the recipient field, recipient ready is the message. But how does it give you the actual content? So right now it does not know how to do it. So it has to be, it has to hold a string. So that string is the actual content which user typed in. And we can exchange the same to message ready as well. So now there are no errors, so this is fine. So now let's see how this would have changed. So you get something. So you can specify the CSS in your Elm code, or you can actually embed Elm on an existing HTML stuff, and you can refer the CSS outside. So for this one, I'm referring the CSS outside. So I'll push this into Heroku, then you'll actually see all the styling and other things. So this is there. Now let me send something, test one. I don't think I'll get anything. So let's see the history what happened. So if you would see the, all these messages are coming as we aside type, but your model is not getting changed, it is still empty. That's because your update function doesn't do anything. So again, I'll copy the update function. So here is my update. I wanted to do one by one, but I think for the sake of time, I'm just copying the entire thing. It's wrong here. What is it? You can say model model. Oh yeah, I just copied the entire thing. Fine, another three, and find the variable notifyResponse. So that's what we missed. So now what does notify do? Notify is like when user clicks on a button. But then we give that to the runtime. Runtime makes the API call. It receives a response. And then we should know when the response comes in. So that's another message. So we need a message for notifyResponse. And I'll just fast forward. So this actually has to be of the type result, error. It should be your notification, notifyResponse. All right? So now it looks like everything is wired in. Now I'll see. Go here. Let's see test two. I have to start it again. Hopefully I'm still connected. Let me just refresh. All right. You got it. So now let's push this onto status. Let's see what all I did. All right. So let it, while this is going through, we'll get back to this one. So what we really saw was I just took a shortcut in the sense I pulled in all the update together, all the view together. You can actually see everything in action if you do one by one, like to only notify then, no. First we had, what we saw was our model was not updated. Irrespective of I'm typing something, the recipient name, the message was not updated. Handling only those two. Then if you click the button, nothing will happen. Then handle the button. Then next is you will not see the response coming and updating it. So you can do it step by step. I just short circuited everything by pulling everything together. But ultimately, this is what we did. So the analysis is thought process goes like what? What's our model? So what are the data that we need? So we wanted a recipient message status in the center. We know what API we are calling, what the expectations are, and what we need to display. The next step is the view. So the view, we had the view function, model forms an input, and it has to produce something which has all these HTML controls in and which generates these messages. When somebody types on the user name field, it sends one message, like recipient ready, message ready, the other one is actual notified. So this understanding, what are the messages that are needed, comes to arriving what messages, what are the types that we need to define. So we need to define recipient set. And we call it recipient ready, I guess. So whatever it is, recipient set, message set, notify, and notify response. And finally, it comes to update. So update has several blocks. It has to handle each of the message. So the first is recipient set. Yeah, I gave you back a no op command. Like I don't want to do anything. I just have to update my model. Next is the message set. I don't want to run any command. I just want to update my model. And this is the actual command notify. Here I send the HTTP command, like do an HTTP post on a particular URL, which a particular body, and all those things. And it updated the model to show that notifying that progress information. And finally, when the response came, I don't want to run any more command. It gave me the new status. So that's pretty much it. So now, I can take any questions, or I have some more things to talk about in terms of how do you. So this is a very simplistic thing. But in a normal UI or normal production, if you want to do it for your production, you'll have multiple components. For example, in this case, in this case itself, how you identify a user is one of the components. The initial log. You can assume that it's a login page. Right now, I don't have passwords. I just have a user ID. Then the actual sending part is another component. Then actual place where you display the messages received is another component. Or maybe it contains multiple subcomponents. And we need to stitch all these together to build a final UI. So let me show you that first. And then I'll take you through the how the what it's kind of pretty straightforward. Like how do you pull in these components? And how do you define what happens to your messages? What happens to your model? How do you map from a components message to your own message, those kind of things? I'll show you. I just quickly just want to deploy this guy so that I can show you what we did. All right, now these apps are getting deployed. I'll show you the code. Yes, sorry. So you want to know the code which click of the button what happened, right? So let's say. So let me increase the font size a bit. So this is the function we generated that button code. So action button. This is the CSS class actually. And this is the message. We defined a message called notify, right? Now this is defined in send utils. So action button or is it action button? Yeah. So what it says is the button, the class is the CSS ID. I want to send this message and the text is sent. So that's what the UI element, the view part of it, right? So what essentially this means is if somebody clicks on it, update function will get a message. The notify message it will get. So we need to go and look at how does update function handle notify? So this part of it, right? So it gets a message, it gets a corresponding model. Yes, it is notify. Probably I should have made it more readable by using a Latin, but anyway it's OK. So this needs to return a tuple of updated model and a command, right? So updated model is, yeah, I'm using the same model. I'm updating this field to say it's just notifying a particular recipient. So that's what you saw when you click on that button, like notifying JS, just show that. And the next is the actual command. So what it says is send this HTTP request. And the first parameter is how do I, what is the message that you should send once the response comes back, right? And this message type is result. It could be an error or it could be an actual response worry, yeah. The next is the actual HTTP request. Now in the HTTP request, in this case it's a post. And this is a URL, it's what I'm, what the URL on which I'm posting. The next is the actual body. In this case, it's a JSON structure that I need to send. And so I have a function which takes the message and sender and creates, gives me back the JSON string. And the final third one is once the response comes, how do I, it'll be a JSON content, how do I decode into my struct or record? So notifyResponse decoder. So the important thing is to defining the mode. This is what we updated, say that, okay, it has two fields and I have a notifyResponse body. So that's it. So this is the command which was sent. Now elm runtime converts into a task and then it'll run the task. And once the response comes back, it will send you back the notifyResponse with either a success or a fail. Any more questions? Yeah. Okay, we'll go through all the things. So this is the sending the notification, right? Then notifyResponse comes back. It's an okay. That means it's successful. If it is successful, it'll have the response body. And the response body is nothing but your notifyResponse body structure that which has status and client ID, right? So here it says, okay, so now I need to update my model to say that, to modify the status message, right? So if it is status is true, that means it is successful. So actually the semantics is that. So this status will indicate whether it's false means the user is not connected. If it is true, means it is successful. So if it is true, then I'll say message sent. If it is not, I'll say message not delivered and client is not connected, whoever the recipient is not connected. In case it's an error, then we show that it's network error or whatever the HTTP error it is. It's a mapping to the string and it shows that error. And here is the way, how do you update the model for whenever user types in something? Message ready means we'll set the message. So your model gets updated incrementally. So I have it. So if you see here, first the model has only recipient j. Now j, a, finally s, then t, blah, blah, blah, blah, blah, all those things. And then finally notify and notify response with just message sent, whatever it is, all right? Any more questions? I think we have 10 more minutes. I don't have a sample code for the ports. Okay, so I don't have a sample code to show, but it is done through subscription. So you can, for example, in this notify code, right? Let me go to the component thing, then I'll cover the subscriptions, so then we'll talk about the ports as well. So let's go back here, fine? All right, so this is the overall application which combines all these three together, right? So let's see how does it look like? I didn't realize last time that I was doing the browser thing, all right? So it would have, hopefully it would have deployed the newer version. Before that, I want to show background images taking while to load, ah, okay. So this is what we built a few minutes back, right? And now this is a consolidated UI, so I'm going to, this I'll say, yeah, yes, connect, apparently test not, deployed the new one, all right? No, that's in a different branch, so. So probably I have to, yeah, this is fine. All right, just a second. We'll get up and running, anything, all right? So let me try redeploying this. Notify by branch, after that. No, that was the previous one. The full complete UI is still in another project, which this should be there, unless something is broken. Oh yeah, it's okay. So just mashing up of all three together. So you have a send message here and the messages over here. So now, so this is the sender which we built, right? So let's say test three, I should see here, yeah, test three, all right? So how did, so in this case, you saw the user connection first and then the send part and this receiving part, right? So I'll go through this notify part. So here, so what the difference is, so your messages notify and there's a tick that will talk about it later and then there's a user login and send info. So the user login is actually from, so what we need is those other tabs, user and send. These are the two modules. So first let's talk about user. So this has only a view for login, like enter the username, user ready. It contains a view, it contains a model and the message, there's an update function over here, right? So now you come here. So you need to wrap that message into your own message structure. So this is user login is your type which contains the actual user message. And then similarly for the send module, send component, you wrap the messages into your own messages. Same thing for model. So you have a user info, users model, notify data, sends model. So essentially those are the two steps. Like in your message, you should wrap your components message, in your model you should wrap your components model. After this, the next important thing is update and view function. So let's look at update. So notify and tick is, this is defined locally in issues. So user login, this comes from a different component, right? In this case, so we have a user message over here. And in this case, I'm doing something where I'm updating the model and sender, that's nothing, that's all. It's essentially not doing any commands or anything like that. But if you look at the send message, that is when somebody clicked on the send button. It comes here, it is calling the sends update method. So if you see here, it's a new model because send has an update, I didn't show you the send. This is what we coded up a few minutes back. So it has its own view, which does everything. It's own update, it's a pretty long update. Notify, notify, response, message, it is what we saw a few minutes back. So it's delegating the update to sends update method. But you would have noticed that in send, your update returns you a model and a command wrapped with the type parameter of the message defined in the send module, not in the main one. So here, you need to map it. So in the command.map, this is the users, you map wrapped into your, otherwise, anyway, compilation will fail. So essentially what it means is delegate your updates, your component and map the messages back to your main message. And it's the same principle for view as well. So if you have view, yeah, okay, it's pretty, okay, it's user-connected-view-model-view, so let me go to user-connected-view. So it's, I'm just calling send-view and I'm calling notify-view. So this is, send-view comes from a different model, notify-view comes from a different model. That's pretty much it. And send-view, if you see here, view returns an HTML message, but send-view will return an HTML send message. So you need to map the message over here to your own message, send it over here. So, and I don't know, I don't know to repeat it, like I just did all these things and then resolved all the compilation error and it just worked. I didn't have to troubleshoot or anything, yeah. No, no, it's the state, it's the model, right? So essentially, if you go back to your update function, so this notify-response, your response on the HTTP call, that comes into update function and update function takes a current model as an input and spits out a new model and another command. It may be no op or it may be a valid command. Now, this updated model goes to the view function. So Elm runtime takes this updated model, calls the view function, and view function decides, oh, this is a new model. As for this new model, my view has to be like this. It gives the DOM, then the runtime does all the virtual DOM comparison and applies the required changes onto the actual DOM, which gets reflected in the browser. I haven't worked on React, I think there are a few others who have worked on React, but what I've read about it, Redux, the architecture is same as Elm, it's from Elm, yeah. Based on who you talk to, based on Elm or inspired from Elm, okay. Essentially, the combination, right, the combining Elm components. So you need to have a message, you need to combine the model and finally delegate view and update to the components. Of course, you need to map the messages. Your component message to your own message, your, yeah, in both the view as well as in the update. All right, and I wanted to show the subscription. That is the Elm test. Yeah, I haven't used it much, though. Beauty of static, so. Most of the time you spend in resolving compilation errors, and then it just works, yeah. Of course, there are, even now, like, the kind of errors that you get are, let's say you're depending on an API. You expect your, see here? Okay, it's not mirroring, yeah. So you expect your response, right? Yeah, message center, your raw message that is coming in or if I go to send, here there'll be notify response body. Now, say API has changed and it no longer sending those two fields, I mean, okay. Those kind of runtime errors are unavoidable, but whatever you are, whatever is in your control, it will catch all of the errors at the compile time. All right, and this, I've given the repose which has this code, like the actual service which is using and both the combined app as well as just the sender part. That's, and any other questions before we, I think we're not on time 45 minutes, yeah. Okay, right now, okay, I've probably in another session, like, it generates the entire, it compiles into JavaScript, right? So you need, when you make, okay, I'll show you this, that should be better. It packages the entire Elm runtime, every time you make and create a something.js. For example, in this one, I can say Elm-make source notify.el minus minus output notify.js, all right? And this notify.js is what is embedded in a HTML file. So if you see here, so script source notify.js and this is how you embed Elm in your, so this is, in this case, this entire page is that, but typically let's say most of the cases where you start is you have already have a big application or I doubt whether anybody builds fully Elm-based ground up application, at least from an adoption point of view, it is like try out in a very small part of your application and see how it is going. So like for example, in our case, like it's a login page alone or maybe some small thing which is on the right-hand side corner of your page dot or it is. So you embed and the suggestion also is to embed Elm into an existing JavaScript application, not the other way. So when you do that, let's say you do it in two different places. Then what happens is then there are browser load two instances of Elm time. So that's, there is no optimization around it. And second is irrespective of what you use. In this case, this is a very simple one. You are using probably HTTP attribute, HTTP event and the basic HTML, but the generated JavaScript will be the entire Elm, whatever the corresponding implementation for the entire Elm stack. So the optimization I think in progress or in weight, in weight are like irrespective of how many times you're embedding Elm have only one rental time. And depending on what you use, like based on that, only that much generated code gets loaded onto it. So those are, now it is 0.18, I don't know, whenever next time happens, optimizations are in place. The next is what else though, I think those are all the, those two are what I can think of on top of my head. And there are certain runtime error scenarios, which one of them I talked about, like the, we are depending on other APIs and that get changed. There are few more cheat sheets, like three or four scenarios where, again, it's like all external dependencies. So it's not completely like, it'll just, if it compiles, it'll work, minus these four scenarios. So those are the shortfalls I can think of. And some people doesn't like, like if it is compiling into JavaScript, why shouldn't we use JavaScript directly? But then why shouldn't we use machine learning, language directory, assembly directories, or byte code directly is another answer to that. So anything else? So there is a published benchmarking. I don't have the link handy, which says it's, it claims it's much better than Angular and it comes second, I don't know what is top and react is even further down. So from a performance point of, it's again the same principle, like virtual DOM difference and applying, that's the same principle. So one of the scenarios were in which enemies recommended is where you want your DOM updates to be faster and performance to be one of the criterias. But again, it depends on whether you're embedding it in small part, you're building everything, entire application based on L and all those kinds of things. But if you ultimately, if you choose to have L membered in multiple parts of your application, it is reported to be really slowing down the browser because it's the multiple run times loaded. And that's the trigger for these optimizations around have only one done time, don't generate the entire end stack, but based on what is really used, all those optimizations. Once probably all those are in place, it'll be much better. Unless you generate the JavaScript and use Node.js, but it is only for UI. It's being built only for UI, it's not for backend. People have built it because ultimately, it's just for it is generated. So if you can make it work with Node, but this language is for building web-wise. It's not for running backend services. Pardon? No, no, no native, only web. Only, only it should be web, yeah. I have a special case for you. Mm-hmm. Mm-hmm. What do you think it is? Mm-hmm. Mm-hmm. Mm-hmm. And I got no plans to work on it. Mm-hmm. And then... That's a hard question. I can't give an SOR no answer, right? I mean I have this information, of course. All right. Thank you, thanks a lot.