Thank you. So I want to evolve my application. I'm going to use Gleam and Erlang. The organization asked for slides, but this is a luster application. So I can't give you the slides. My name is Kiro van Gelder. I'm a freelancer from my own company. I've been using software for up to 30 years since I don't know how many platforms, languages, environments. And I happen to like to beam Erlang, Gleam, etc. So that's why I picked it. That's not only why I picked it. So recently I was at Langdev, model-driven stuff, all kinds of things that people showed us. One talk that spiked my interest was about, okay, well, we have a game. We have a description of a game. And while we're running the game, there's people interacting with the game. Well, there's things we don't quite like, so we're going to change the rules. And then we have to keep, the game has to keep running. So, yeah, well, okay, that looked awesome. So I thought I can build something like that, but I'm going to do it on Beam. Beam has these superpowers, all the reloading and things are, it seems really suited for it, so why not? And then the other thing I thought, well, if I want to do that with a game, and I have to build some kind of infrastructure and things, let's start with a simple game. So I picked out Holland's Ganserbord. You have a little goose spawn, and you have to reach the very middle spot. And if you look at it from the model and the rules, there's actually quite a few of interesting exceptions for all the kinds of places that you can run around on. And land on a goose, you have to move twice as far. You can skip it during, if you're in prison, well, you can only get released when someone else releases you. It's kind of special. So what will I talk about? Tiny introduction on model-driven development. I'm going to tell you why I do the modeling game. I'm going to explain a little bit about dynamic reloading as the Beam provides it for those who might not know it. I'm going to tell you why the game itself, the instance will be running in core Erlang, and that will be demos all along. Model-driven development. You want to have some model. It needs to have a very precise description, and at some point, me as an editor, sometimes in a computer editor, will make that description. And from that description, we generate an instance that is running what we described. Why would you want to do that? Instances sometimes are, well, they're compiled targets, and they know the things that they have to do, but they don't know things about themselves. A model is a description that does know it. A very nice example that was given on that Langdef was about Dutch income tax. This is described in laws. Computers do not interpret laws, but they went through the effort to take the law, adjust it a little bit so they did it together with lawyers to make sure you got something that a computer could interpret. So laws might have ambiguities or vagueness things in there. Computers don't. Well, then they had these more precise versions of the law, and they, from that model, they generated Java code. Dutch income tax is running on Java code at the moment. Additional things you can do once you have it in the model is you can start reasoning about it. So by now, I understand that even if they want to introduce a new law, they can, you can just plug it in the system and see is there any contradiction here. If so, please adjust this law proposal. Often you'll have a domain specific language like the adjusted law. For my conserboard, you could have stuff like this. Often people will want to edit these DSLs by hand, but I'm very much interested in small deltas. If I have a running game and I make a big modification in here, I don't have a game. So I need to make sure I do a small step, a small delta. So I have to, with what I do, I have to restrict the possible edits that can be done, which I call deltas. How does that look? Building a system called Eagle. It's running on a server. That is, I have a browser. That's my client. From the client, I do the editing of the model. From there, I generate my instance, my game, and then from the same or a different browser, I view the game and I play the game. Why would I want to do a modeling GLEAM? The model should be as precise as possible as I just explained. GLEAM gives us types. Type safety is more than non-type safety. So my name is GLEAM. Other benefit, a superpower of GLEAM, you can compile it both to Erlang and to JavaScript. So I can, if I have my model and I can somehow transmit it, I can just use the exact same code on both sides of my client server and I know that it's the same thing. It saves me work. What does it look like? I have my model here. So in my LusterUp, I now have an iframe. This iframe is the model client that I showed in the previous picture. It's an iframe, so it's a web page, but as you might guess, that web page again is a LusterUp. And I want to grow the Hanzer board from as minimal a thing as possible in small deltas. So let's see where we can start. My model is very simple. It's a bit too simple here, so I need a bit more of a model. I can make a list of an int. I could even make a list of a list of an int and it's represented here. And I not only want to describe that I have some type, it also needs to have some default value. In addition to that, we have a cell. My Hanzer board isn't quite finished yet. Sorry. I have a plain cell starting to finish and I might even use the goose. And right now what I also have then is a game type. It has a board which has a list of cells and it has pawns which are a list of numbers indexing where the pawns are. It's a choice. There are other choices. And the default of my Hanzer board then has one cell at the moment which is plain, which is a bit ridiculous. So let's add a few more cells and say we're going to start at some of these things. And of course the default that I gave to the int turned out to be a bit awkward because I wanted it to be zero. So I mess a bit with my model. In very small steps, I modify my description to get hopefully to a better place. Dynamic reload. Erlang and beam provides us the tools to do these timing upload. This is a loop. Usually there's a process running on the beam that is executing this loop. It had been started by another process. And generally it receives messages, handles them, sends back some results. That's what the from exclamation mark is. It sends back some result. Could be errors. Could be part of the new state. And then it loops. And another possible message could be well just stop and then you don't loop. All there is to it. What Erlang and beam also provide is a way to reload, sorry, to load new code into your, into the beam for a specific module. That's the code module in the Erlang kernel package. You call it binary here in the middle. Target is the target module. The thing in square brackets is the file name that it would be coming from. We don't care. And the object code is compiled core Erlang code. At that point when you do that, you have your old version of the code in the beam and you have a new version of the code in the beam. But the existing processes, my game, my Hansbord is still running the old stuff. So now I'm going to send a message upgrade to my Hansbord process. And roughly like that this is the same loop as before but now I have the relevant upgrade part. Instead of just looping, which would loop in my old code, I have to say format this module for my target module, my Hansbord module, explicitly specify the module with the loop and then it's guaranteed to use the new version of the code. And then I can happily play along my game with upgraded code. Now why do we do that in Erlang? The difference between the local loop and the exported loop is something that Gleam does not know. So I can't do it. Why did I pick core Erlang? Because we can do this all in memory. No need to use file systems and other things. There is an Erlang C-E-R-L library that can generate these things. I wrapped it for Gleam. That's called Gencore Erlang and you can find it on the hex. So let's start a game. I already made the type properly. So I'm ready to create a game. If I connect to the server it won't do anything here, but if I create an instance it's now and it will connect to the game. So as you can see, it picked up the start plain plain from the definitions that I had at the left. It also picked up a move button. The rules, there are some implicit rules that I did not edit things about. I did not tell anything about. I need to be able to do something in my game. So there's a hard code that moves. I will just move the pawn one forward. And there's also a check for the win condition. So where the pawn is, it has to check on the board whether that's a finished location. And that rule is going on continuously. I have not made nice deltas and things for that in the UI and when at some point I will. But these things are running in the background in the instance. Now at least I'll show you the move. If I move, my pawn moves one forward. So yay, getting closer to the finish in my GUNS board. All right. So a little bit more about the bits and pieces that are happening. There's the Asian communication from the browser to the server for the model. Whenever there is a delta that's made, we just recreate the entire instance module in Core Erlang, reloaded and upgraded. And the instance just keeps talking to it. It doesn't even notice it from the client and also talks in terms of chasing with it. State and rules. The initial state is something that should be adopted, adjusted and rules are... So yeah, that's right. The rule is something that is in the model. I talk about a conceptual thing there. My instance doesn't know the rule. It just has code. And my client doesn't know what the rule is either. It just knows whether it can do something or cannot do something. So what is important that I wanted to make as two kind of changes. Some changes that when I do that, the instance will in the end see it. So I'm going to change the board. And that when I change the board it's going to compile the change into the Core Erlang, reload it, do some small migration and then also pass that information to our client. So, here we have it again. If I turn this into a Goose for instance, it becomes a Goose. So that was one recompilation of Erlang in the back button. Now I make another plane. I can add another one if I want to. And at some point I'm going to have to reach the finish here. So let's make that. So yeah, that was three, four recompilations of things in memory and moving on. Involving. But another one thing that I might want to change, because I can also create multiple instances, is my starting state. And that would mean that the only thing that happens if I change that from my client, it changes my model, but nothing else, unless I don't start a new instance, nothing happens with it. And that looks like this. So I have a game one and a game two. Game two hasn't been started yet. And if I change this one from zero to one, now I start at position one. Then we notice that in game one nothing happened. But if I start a new instance, then this one will now start at position one instead of position zero. And just to show that even though it shows two, it didn't change to one, but didn't show it. If I move, it will go to three. Well, and where did I put the finish today? On start, zero, one, three, on number four. I'll just move to four. There. I finished my game. I won. So things I want to do in the future. I'm very much interested in what kind of deltas are usable, sensible. You saw me adding cells to a board. You saw me change the type of the board. Okay. What if I remove a cell from the board? Yeah. What if the pawn is on there? It quickly becomes like, you could think of a couple of solutions for when you remove the cell from the board. You move the pawn to the previous or the next cell, or you remove it, or you put it on cell zero. But why would, why, how do you pick one? Depends on your application. So I really want to look more into that. Another thing is that I don't think the Hanselboard UI that I had looks very nice. It would be much better if it looked like the second slide that I showed. But if I do that, then the client really knows about Hanselboard. But what if I want to make a slightly different game? So, okay. And what if my Hanselboard knows about most of the things I do, but I add that labyrinth thing? Now I want to render a nice labyrinth. Okay. Can I make something that knows its Hanselboard, but can also adjust to changes that I make in the model that expands on what was already there that they didn't know about in the start? And obviously, it needs to be multiplayer because playing in my own is, I want you all to play with me. All right. The code that you saw in the iframes is in the top link. While reasoning about this, I also wrote a little, a start of a Gleam library that generates Gleam code, which is the second link, the one that generates Core Erlang. It's the third link, my own web page, the fourth. And if you want to know what the Dutch income text is looking like, it's all in there. Thank you. We have time for a couple of questions. Anyone? Any? Okay. Thank you. That was really quite amazing technology there. I was wondering, do you have thoughts on like when you might decide to apply these sorts of techniques to a problem? When it would be a good question. Yeah. Okay. Question is when this kind of solution would apply to a problem. It's, I might not be the best person to answer this because I'm somewhat new to model driven. It helps when you, when that description is going to give you something, whether that is checking that something is coherent or correct. When, yeah, the model should give you something. When not to do it, well, if you just want to play Hansenboard, just make a Hansenboard server and a Hansenboard client because it's much faster. Much quicker to build. So it's, it's, it is an investment. It's quite an investment. It's not just, not 10% extra. It's a factor much, possibly 5, 10 extra to make sure that you can really do that kind of stuff. Other question? It was the same question. Because it's fun. Okay. Yeah, that was really, really cool. Really interesting. When you changed like the initial state, you showed like the running client didn't update, right? Like it didn't, it didn't update the client because all these updates are triggered through messages. Is it possible that you could replay message history from the beginning with a running client? So like if I updated the initial state of a running process, could I then replay all of the messages it's received to change propagates? There's, there's, there's two answers to that, I guess. Yeah. Is it possible to replay all the events that happened both to the model and the instance or just to the instance game? Just to the instance. Just to the instance. At the moment, no. Would you? Would be, would be interesting. One way in which at least the part of the answer would be yes is if you look at the model when I, when I say please change this in this way with this delta, the server will respond by just giving you back, yep, I applied this delta, now you do too. Okay, cool. Any other questions? Okay, thank you then. Thank you. Thank you.