Dwayne Crooks stops in to share his appreciation of algorithms, experience learning Elm, challenges building Elm 2048, and how he uses Elm at work to build things like the decentralized finance app, Qoda.
Dwayne Crooks stops in to share his appreciation of algorithms, experience learning Elm, challenges building Elm 2048, and how he uses Elm at work to build things like the decentralized finance app, Qoda.
Thanks to our sponsor, Logistically. Email: elmtown@logisticallyinc.com.
Music by Jesse Moore.
Recording date: 2023.03.07
Jared makes generalizations here that work well for many cases but do not apply for every situation. For example, interop with UI tools such as a map would make more sense with custom elements rather than ports.
Check out Dwayne's post on Discourse explaining how ports are used in Qoda.
If you're stuck, please ask the community on Elm Slack or Discourse.
Disclaimer: Comments about how Evan works are based on our outside observations.
[00:00:00] Jared: Hey folks. Welcome back to Elm Town. I'm your host, Jared Smith. We'll be visiting with Dwayne Crooks today. But first, let me talk about our sponsor. Logistically is the company where I work at Logistically. We make transportation management software for third party logistics companies and shippers. I'm grateful that Logistically pays me to spend a bit of my time recording Elm Town episodes, as well as pays for our recurring production and hosting costs.
[00:00:32] We build the front end for all new features in Elm. I just looked. We have over 100,000 lines of Elm code in production. We're eager to talk to folks who enjoy writing Elm. Please drop us a line, elmtown@logisticallyinc.com. I'll put a link in the show notes.
[00:00:56] Jared: So, introducing Dwayne Crooks. Now, his community contributions include maintaining the Built with Elm website. Recently published package, Elm Natural, the 2048 game in Elm, and, that's just a few of them. Let's get into it. Dwayne,
[00:01:17] welcome Elm Town.
[00:01:18] Dwayne: Hey. Hi Jared. Thanks for having me. So I'm from the beautiful Caribbean island called, um, Trinidad Tobago, and I've been programming. For quite some time now. I've been doing it professionally for almost 12 years, um, as a web developer and I currently maintain the Build with Elm website as well as, um, uh, the, I wrote the Elm 2048 clone that you guys might have seen recently.
[00:01:49] Jared: Yeah, it's beautiful.
[00:01:51] Jared: Um, when you were starting out in programming, what was that like? Would you tell us, maybe go back a little bit and tell us about how you became interested in programming or knew that that's what you wanted to do.
[00:02:02] Dwayne: Yeah, sure. So when I was younger, I was interested in playing video games, as we probably all were. And, um, I, I enjoyed playing like fighting games and sports games and stuff like that. And so when I got my first computer, I wanted to build a Street Fighter-like game. And so I taught myself C and something called the Allegro Game Programming Library.
[00:02:29] And I attempted to build it, but I realized that, um, you know, I, I wouldn't be able to complete it because I needed more skills, um, besides programming skills and I really didn't want to learn those extra skills like the graphic design stuff and some production stuff. But I, I was interested in, in solving problems and designing algorithms.
[00:02:53] And I discovered that the best place to, to do that was in something called algorithmic programming competitions. So I would train on USACO problems, USACO stands, farm, United States of America, um, computing Olympia. So they had like a training area where you can go and train on these, on these problems to get better.
[00:03:14] And then I'd compete in top quarter, um, competitions. And so, so that was where I got into programming and, and got a love for it. And from there it led me into university where I studied, uh, math and computer science and yeah, so, so that was the start of, of my love for programming. That's it.
[00:03:36] Jared: Oh, neat. Okay, so this, you said Osaka program. Did I say that correctly?
[00:03:41] Dwayne: U S A C O.
[00:03:43] Jared: Okay. USACO. Okay. And that around what age were you when you were doing that?
[00:03:52] Dwayne: , I guess it's, it was probably around the age of 15, 16, somewhere there.
[00:03:58] Jared: Okay.
[00:03:59] Dwayne: Yeah.
[00:03:59] Jared: So you were programming for a couple of years, and then when did you go, uh, at this point, I'm guessing, uh, before you went to college, is that correct? Went to the university. Okay.
[00:04:11] Dwayne: Yeah. So, yeah, so I was programming in, in secondary school, um, which is the equivalent of high school in the any states. And, um, I studied something called information technology there. And so I was programming all throughout high school for my final year project. For example, I, I wrote a, a music program in Pascal, so you can, like, there was a staff on the screen and you can put you can put your notes onto the staff and you can play, play a tune.
[00:04:39] On it. And so to build that, um, so it was in Pascal and it was a MS stores program. And, um, it was, it was, it was interesting. I didn't like a lot of, um, neat data structures and stuff to, to get that built.
[00:04:55] Jared: Oh, cool. Yeah. So did you have to, uh, learn about some music theory as well? Or was it simple enough that there wasn't much to learn there? Or did you already know those things?
[00:05:07] Dwayne: No, I, I didn't know those things, but I didn't have to learn anything about music theory to build it. It was simply enough to, uh, yeah, to build without that knowledge.
[00:05:15] Jared: Okay. Yeah. So that's good. You could focus on the algorithms, the part that you love. Right.
[00:05:20] Dwayne: Yes.
[00:05:21] Jared: Yeah.
[00:05:23] Excellent, excellent. So you've been programming professionally for about 12 years. Before that you were, um, at the university and, and you had completed this, uh, USACO program
[00:05:37] Jared: Before that, um, at what point did you discover Elm.
[00:05:43] Dwayne: Sure. So , it was in one of my previous jobs where, um, I was working on a large React code base, and this code base was becoming a nightmare to maintain. And so I was, I was actually on the, on the lookout for something that would help me, improve the solution that we had. And I think I stumbled upon it fire, maybe I'd say a Hacker News post.
[00:06:10] I, I, I don't know for sure, but yeah, I'd say Hacker News post. And I, I read, I read about it and, um, it seemed, it seemed interesting. And so I decided to try it out on a couple site projects and, um, that went well. And so I tried it out on a small feature that we, that we had in work that, um, that I thought could use some refactoring.
[00:06:35] And so I tried it out there. And when, when I build the solution, um, it went from like having 10 plus files, um, to, to just this one Elm file that was like well structured and it was easy to reasonable code and everything like that. And so that impressed me a lot. And so I, and so that's it. That was my first encounter with Elm.
[00:07:00] Jared: Okay. Yeah. And so this react code base, you said that you're, the problem you were trying to solve with that was the maintainability of a large code base. Is that correct?
[00:07:10] Dwayne: Yeah.
[00:07:11] Jared: Yeah,
[00:07:11] Dwayne: Um, so just add to that. So before that, so I was like doing programming competitions and I was like writing small applications. So maintainability was never really an issue, but it was at this company where we, like, I worked there for a little more than five years and, you know, as time progressed we have to make changes to the code and changes were progressively getting difficult.
[00:07:35] And so I was just looking for, um, to make my life easier.
[00:07:40] Jared: Yeah, of course. Yeah, that sounds familiar to my journey as well. I, um, was looking for something that was more maintainable, but also I was really looking for, um, the quality I was working in healthcare and, uh, the reliability of, of Elm just sounded like something that that would be, uh, really useful in my domain.
[00:08:04] But, but yeah, maintainability is, is huge. And of course, the ability to, uh, refactor so seamlessly with Elm is, um, un unbeatable in my opinion, but it's biased. So, um, so then, You put this little piece of Elm in this large code base, uh, what happens then?
[00:08:29] Dwayne: Yeah, so I, I open a PR and I tell my, so I, I did it and I did it, like on this side. I didn't tell anybody that I was doing it. I just wanted to convince myself that, you know, this, what could be a viable solution. And then I opened this PR and I shared it with my teammates and they, they liked it. But unfortunately, , Like, even though my, my cto, um, saw the benefit that it brought it wasn't ultimately merged into the code base, um, for a variety of reasons.
[00:08:58] Um, we, we recently moved our code base from like using e s six and a backbone JS style application over to React and started using ES 20 16 and, and stuff like that. So it was, and we moved from coffee script. So it was like we were already in a transition phase and then to come and, um, ask to have Elm this new style of programming language and this new way of thinking about department solving, it was like, might have been a good non-team.
[00:09:31] And so ultimately we, we didn't, yeah, we didn't include any equal base, but that experience that I had would, Elm, really made me want to get. Like better at Elm and be a better advocate for Elm.
[00:09:45] Jared: Oh yeah. So for you it was a win either way. But I understand that position of being in, uh, in where it's, you know, it's a lot, right? There's a lot going on already. So, um, to try to do, introduce anything new no matter what, it's, you know, it's just, uh, you're already transitioning that. That makes a lot of sense.
[00:10:04] Jared: When you were had found Elm at this point, did you previously have experience with functional programming?
[00:10:12] Dwayne: Yes, I did actually. So at university, although we, we never studied functional programming. There was a professor who I, um, spoke with and he, he actually put me onto functional programming. Um, he referred me to like a few books on a topic, and one of them was S I C P actually. And so my first introduction to functional programming was, was through s i p.
[00:10:38] Jared: Okay, cool. And I am not, I, I've, I've heard of that book, but I don't, I haven't read it. I don't know the details. Could you tell us a little bit more about it? What language is used in there?
[00:10:50] Dwayne: Sure. So, s i p stands first, the structure and interpretation of computer programs. And it was this famous book written by Gerald Sussman and Harold Abelson in. I want to say in the early 1980s. Um, and it was used in like the introduction computer science course at m i t. So it's famously known as a, as a, as a hard book, as a difficult book to get through.
[00:11:16] But it does have like a lot of great concepts in it. And so, um, it's, it's written, uh, the concepts are explained through, um, the Scheme programming language. And like the first chapter is like a masterclass on functional programming. It teaches you about higher order functions, uh, like map, filter, fold, et cetera, and fu and it about first class functions, like having functions as data structures, um, being able to pass functions to the other functions or the return functions.
[00:11:49] And it, like, it, it gives you this, um, a good foundation in, in that style of programming. So it was a good introduction.
[00:11:57] Jared: Okay. Yeah, that sounds like you would really have a lot of knowledge that like, for example, myself, when I was, , starting with Elm, I did not have experience with functional programming. I had tons of object oriented programming experience. I had not read any books at the university. We learned Java, so, you know, it was all OOP all the way down, you know.
[00:12:23] Um, but the, the way that Elm taught me functional programming, you know, the guides and, and the, the people in the community who, uh, were putting out blog posts and recording videos explained it in such a way that I didn't have to know a lot of that. I mean, I, I sought it out. In a, in a bit of a way of, you know, what is this thing, you know, what's really going on here? But I never had to learn about things like, you know, the, the M word monad or, you know, any of those types of things. So, were those concepts that you learned, uh, through that book, those those terminology, was that, is that part of it?
[00:13:08] Dwayne: Um, at this, some of the concepts I learned should that book, um, monad isn't talked about in art book, so I didn't learn it there. Um, I, I'd also like experiment on the side with, with new languages from time to time. And so I did experiment with Haskell and was introduced to monads through there. Um, it was for me as well a difficult concept to, to understand at fus, um, because it's, it's usually presented through a lot of examples in a lot of ways, and it, it can, it can become confusing, but.
[00:13:40] Yeah. So through experimentation. Yeah. I would like, through experimenting with other languages, I would, I would learn other concepts as well.
[00:13:47] Jared: Okay. All right.
[00:13:49] Jared: Well, I want to talk about your transition now because you said this company where you had introduced Elm into the React go base, or you know, you had experimented with it. Was that a previous company? So could you tell me a little bit about what happened after you'd done that? After you had started experimenting with Elm on the side, working with it more on in your own free time?
[00:14:15] Uh, how did you go, where did you go from there?
[00:14:19] Dwayne: Sure. So, after being rejected, um, at that company with trying to introduce Elm, um, I stayed there for a file for a little while longer, but then I, I ultimately left there and in the interim I decided to do more of a deep dive on Elm to to learn it better. And so I do like little side projects to get familiar with it.
[00:14:44] One of the things that I did was to so there's Free Code Camp and they, they have this curriculum that teaches you JavaScript and at the end of the curriculum, they give you like five projects to do to test your skills. And so I decided that I would do those five projects in Elm to, um, see if I really understand the language and if I can actually build a, a UI in it.
[00:15:07] And so I did that, and then I came up with a few other projects that are due to test various, um, ideas that I had to ensure that I can work with it , better. And then, how far do you want me to go? Go along with
[00:15:23] Jared: Well, as deep as you would like. I, we have time, so yeah. Let's, let's get into it. Tell me more.
[00:15:31] Dwayne: Sure. So, yeah. so after completing those five projects, which which were like, um, a random quote machine, uh, markdown, previewer, um, something called a drum machine and a calculator. So they all allowed me to Experiment with different ideas that I had. Um, I wanted to understand more how to build reusable views.
[00:15:55] I read Evan's code on, um, the Elm sortable table. And that, um, inspired me to try to build a reusable view, and that is what became something called elm-rater. Um, elm-rater is like a star rating widget that you can customize in any way you like to to add to that as like a, as a component to your project, as a widget to your project.
[00:16:23] And so that helped me understand how to build reusable views a little better. And then I, I also wanted to learn how, how to separate like the business logic from the user interface. And so in order to do that, I, I, I tried to build, um, tic-Tac, uh, small Tic-Tac to Game and Elm 2048.
[00:16:46] Dwayne: So the initial version of Elm 20 2048 didn't have animations at that point.
[00:16:51] And, but it, it was, um, one of the projects that helped me understand how to, how to separate a business logic from the UI because I, I didn't want, I wanted to be able to easily test the code without having to go through the, the user interface and,
[00:17:07] Jared: Okay.
[00:17:07] yeah.
[00:17:07] Dwayne: yeah.
[00:17:09] Jared: the Elm 2048 game that you made with the animations is just incredible. I, I love playing that. Um, I wanted to ask you, throughout that building that game, what were the obstacles that you faced when you were creating it?
[00:17:27] Dwayne: Sure. Well, the, the major obstacle I, I faced was actually getting the animation. So my goal at the start of the project was how do I separate the business logic or the game logic in this case from the user interface under the clean separation and what animations it, it seemed as though if I introduced it, or when I wa the first time I tried it, when I was introducing it, it like it caused an entanglement that made it hard to test the program and to understand the program.
[00:18:04] So like it was getting in the way. So this process happened over a period of time and then I realized that maybe I can return a value. From the business logic side that describes what happens when you move the grid so that the UI side can interpret that value and then, and then display, um, what needs to happen.
[00:18:29] So, um, so I figured out that I needed to give the grid a little bit more structure so that the UI side could, um, could interpret that structure. I can go into more detail as to how, um, like what that structure is and how it works if you want.
[00:18:46] Jared: Sure. Yeah. I guess to kind of reiterate and make sure I understand your original goal was to. Cleanly separate the business logic of the game from the UI of it.
[00:19:00] Dwayne: Yeah.
[00:19:00] Jared: And the part where you struggled was the animation that was the challenge that you faced where they were becoming entangled, um, with the, the ui.
[00:19:10] And so you felt like maybe at that point you did not have that clean separation that you had hoped for. Okay. And so, and so you created some structure that allowed you to create a better separation. Yeah. Let's, let's talk, you don't have to get too much into detail as, as far as trying to describe code.
[00:19:31] Jared: Um, I think Dillon Kearns and Jeroen Engels on Elm Radio do such a great job of describing code, but, uh, for me, I, I, I'm not so, so good so, good at that. So yeah.
[00:19:46] Jared: But if you do have a way of describing it, um, it comes to mind. Let's, let's go for it.
[00:19:52] Dwayne: Sure. So, I'll take it from a high level. I don't necessarily need to describe the code, but I like describe what happens at a high level. So, um, I was able to come up with this grid structure. So let's, let's think. In, um, in 2048, there's, there's a four by four grid. Let's just reduce it down to a one by four grid.
[00:20:12] So one rule, and I'd go through like three scenarios to explain what happens. Um, so in your first scenario, let's suppose in this one by four grid, we have a tile, um, which is, um, the tile with a number two on it, and you want to move it to the, to the right. So it's at the far left and you want to move it to the right.
[00:20:32] Jared: Okay. And, and just to the, the goal of this game is to combine tiles that have the same numbers.
[00:20:40] And so they add together, and then you keep combining those. So you add two and two, make four, and then you add two, another two and two to make four again, and then you can combine those two fours to make eight.
[00:20:53] The goal of the game is to keep adding those numbers up until you get to 2048.
[00:21:00] Dwayne: Yes. Yes, exactly.
[00:21:02] Yeah. So in this scenario, if we, if we move the tile across to the far right, like there's no issue there. Um, the animation is simply to, to move, to move the tile. Um, but there are other ways the tile could interact with other tiles. So the structure of the, the grid is such that their, um, tiles could be in various states.
[00:21:23] So it can be a new tile, it could be a composite tile or a merge tile, or an old tile. New tiles are tiles that get added, um, after a successful move. Um, composite tiles are these tiles that, that get merged. So in the first case, we didn't have, um, two was a new tile. It, it didn't merge with anything. And so when it moved across, it became an old tile essentially.
[00:21:48] The next scenario is, let's suppose we have a two tiles, a , two and a four on the far left, and then you want to move it to the right, well, it's two and four. There's nothing else. So there's no merges happening. And so again, this is a scenario where the two and four just slide across and it becomes an old tile, but it becomes an old tile with, um, there's a, um, there's a structure within, um, within there that tells you where the tiles moved from.
[00:22:20] So that when I returned it to the ui, I'd say these tiles were at. So for example, two was at position one, one and four was at position one, two, and these tiles moved two position. The two tile moved to position, um, three, four, and the four tile moved to position four. Four, and that's it. And so when the UI C sees that information, it knows.
[00:22:43] Now this is a, a move to instruction, if you will, and it, it does an animation to move those tiles. The, the final scenario, which is, which is where the complication comes in, is say we have two tiles, uh, two and a two and on, it's on the far left. And you want to move it to the far right. Um, well, when it moves to the far right, it is supposed to combine with the. The twos are supposed to combine to become four, and that four is supposed to dissolve into the, into the screen. And that, sorry, the twos are supposed to dissolve into the screen and the four pops back out. And then you have the four tile. So how the, the structure looks in that case is that what we have two, two being old, that moves across the screen.
[00:23:32] Um, both become merged tiles and emerge. Um, the merged state has information that says these tiles moved from moved from, um, one, one and one two to, to, um, 44. Both of them move to 44. And it also adds a new tile called a composite tile, um, which is the four. And so when I return that value to the, to the user interface, it can interpret the merge and the composite and say, well, let's first move these two tiles across the screen, dissolve them, and then pop out the composite tile and all this, all this stuff has to live in the DOM because of how the, an the, the, the values need, the, the do structures need to be there in the do so that the DOM can do the animation correctly.
[00:24:28] Yeah.
[00:24:28] Jared: Right, right. Yeah, I've experienced that before too. You need the previous state in order for it to calculate how to get to the next state.
[00:24:35] Dwayne: yes.
[00:24:36] Jared: Yeah. Yeah, that makes sense. And you explained that really well. Thank you. I think that, um, the result of all your hard work on that, um, is, is great. It's just such a, um, it's so enjoyable to complete those, you know, to do those merges when you see them, them come together and the colors change.
[00:24:56] And so that, um, came out really well. It's, it's so fluid and so thank you for putting all the, the work into, to making that. Uh, I've been playing it a lot recently as we've prepared for this.
[00:25:10] Dwayne: Yeah. Yeah, that's, that's great to hear. I was, I was, um, addicted to the game when it first came out, so, so that's why I was, I had, I had such interest in it and like, it was, it was really painting me that I couldn't figure out how to get the animations done. So, um, I was happy when I, when I finally figured it out and I got appreciate all the good feedback that I got about it as well.
[00:25:30] Jared: Good. Yeah. And so at that point then, You felt like you had solved that puzzle, right? You had found out how to really separate the business logic from the ui. And, uh, and so did you feel like then it was testable? Did you add tests for it or how, you know, what, how did you really know at that point you would succeeded just by looking at the code and working with it or, or what?
[00:26:02] Dwayne: Yeah, I did, I did write a few tests, but I didn't go overboard with the tests. But, um, yeah, based on the structure of the code, I, I knew I accomplished what I, what I wanted to, to accomplish. I was able to like instantiate the, the game logic outside of whatever UI it was and test it out manually. Um, but I didn't write, um, automated tests, like much automated tests for it, but yeah.
[00:26:28] Jared: Sure. Yeah. So I had worked on a game at one point, uh, 3D pool game with Andrey Kuzmin. And when I had approached him with this idea, this was kind of my goal. I was like, okay, I don't know much about doing 3d. And you, he had at that point done a little demo of some, uh, pool or billiard balls, you know, rolling around on the table.
[00:26:59] And, but I have a lot of experience, uh, playing pool. Uh, I played in a league, uh, an amateur league for a while, and so I, I understood the rules and I thought, you know, if we could separate this so that, you know, he worked on the part that displayed and, you know, and, and calculated all of the 3d, all the hard stuff right in my eyes.
[00:27:20] Um, and then I could just focus on the business logic, the of, of playing pool, which I was like, oh, okay. This is the easy stuff. Then I could figure out, you know, uh, how, how to be, how to be, uh, productive in this, uh, in building this game. Uh, and, and it turned out really well. I wrote a blog post about it, so I, I won't go into too much detail here.
[00:27:42] This is what it's about, but I just, that concept of being able to separate business logic in ui. uh, works really well when you find out, when you kind of tune it and get your data structures just right. I, I agree. Um, we had a, a just one little bit of, uh, of detail on it where we would, um, do run this calculation, um, that required no knowledge of, um, of 3D logic.
[00:28:08] It, it wouldn't even have to be a 3d, uh, rendering of the pool game. All you needed to know was, you know, what state the, the balls were in when you started. And then it would calculate and say, you know, what, what are the possible next states? Or, you know, what next state is it in? Um, and, and return that. Uh, and so that, um, worked out really well and I was able to write unit tests for that, uh, without even having to go through the ui.
[00:28:35] So, um, it sounds like it's a similar, uh, process of, of just figuring out how to get that structure right so that you can. Have that information, uh, in data form.
[00:28:48] Dwayne: Yes.
[00:28:49] Yes.
[00:28:50] Jared: Yeah. Excellent. All right, so you were building these games and, um, you were really getting deep into understanding how Elm works, how to structure programs in a nice way. And then you're still working at this, at this place, uh, you've been working at Correct. At this point, or had you already moved on, or
[00:29:15] Dwayne: Um, I already moved on. So the, the Elm 20, the, uh, the 2048 game is actually a more recent, um, is a more recent project that I completed. So I, I built the, the first version of it without animations a long time ago. But the, the discovery of how to do it with animations is, is more recent. So we like kind of skipped across like a, um, a few things.
[00:29:39] So at this point, um, um, at my current company, I am real folk and I'm doing, um, actually doing, um, um, in production. And so that's when the realization how to add the animations to 2048 comes in.
[00:29:56] Dwayne: But there's like some stuff before that we could probably go back to.
[00:29:59] Jared: Yeah, sure. Uh, what happens in between there? You know, you build this first version of, of 2048, and then some things happen and you, you build another version. Um, let's get into those details if you want to.
[00:30:13] Dwayne: Yeah, sure. So, so after learning as much as I can learn, building, um, I'd say like one page applications, applications without any routing and stuff like that, um, I wanted to try to build applications that did include routing. So I I, I looked for tutorials. Um, these tutorials were in like other, other frameworks like React and Ember js and stuff like that.
[00:30:36] And so I, I built something called Super Rentals, um, which is a tutorial From the Ember js community that goes, that goes and shows you how to build, um, this web application that has routing and some other stuff. And after building these like toy projects, I decided that, uh, maybe I can use my skills to, um, work and to contribute to something.
[00:31:01] And so I looked, I looked around to see what was there, and I saw that it was built with Elm and um, it wasn't being actively maintained. Like I saw that there was some issues open and also people had PRS open for, for, for some of the issues as well. But, um, no activity was happening. So I decided to reach out on, um, on Slack with.
[00:31:22] The current mana and, um, I told him like I wanted to con, I wanted to make a contribution to the project, but I saw that like there was no activity going on and like what he processed to like, to contribute. And, um, I got no response. But, um, after a few weeks, Evan actually reached out to me and he told me, um, like he would come out with a plan for my changes to be added if I actually go ahead and do what I say I plan to do.
[00:31:52] And so I, so I went back and I, I made the changes and reached out to Evan again. And, um, he coordinated with, with Luke, um, Wes Biso, Luke Westby has actually, actually the original creator of, , of the Built With Elm project. And he owned the domain and, um, rights did, um, like make merges to code and stuff like that.
[00:32:17] And so he reached out to him and told him that, um, that I wanted to contribute. And, they decided that the best course of action was, was to actually give, give me, um, like full access to the project, like make me become an owner on the project. Um, because they, they like the contributions that I was, that I was making and I was enthusiastic about like, trying to maintain it.
[00:32:38] And so they gave me ownership of the, of the project and, um, it went from there. Um, I made more changes. I added, I added some projects that they had submissions but they weren't added to the project as yet. And, and then I announced it on, on discourse and it went from there.
[00:32:58] Jared: Yeah. Thank you so much for maintaining built with Elm and, and that's, I think, a huge, uh, contribution to the community. Um, so you're still maintaining built with Elm, is that correct?
[00:33:13] Dwayne: Yeah, I'm still actively maintaining it though. I'm not actively asking for submissions or going out and getting submissions, but I'm ensuring that the code base is up and, um, and that, um, when submissions do come in that they're added promptly. Uh, a friend, um, expressed interest in, in the, in doing a redesign of the site.
[00:33:33] So I'm excited for that to see, uh, to see, um, to, to, to build that and, and to contribute that to the, to the project. So we'll see.
[00:33:43] Jared: Oh yeah. That, that sounds exciting too. Well, yeah, I think that it's a, it's a project that. Um, I'm glad we can talk about, because I would like more, um, more things to see on there. I'm, I'm really, every time I go to it, I, you know, look and see what's new from the last time. So, um, so yeah, if there were a redesign, that would be pretty cool too.
[00:34:08] Dwayne: Yeah,
[00:34:10] Jared: All right. So at this point, you are becoming more and more involved in the Elm community. You, you mentioned that you are now an engineer at real folk. Uh, do you want to tell us a little bit about that, about how you came to work there and what you do there?
[00:34:31] Dwayne: sure. So after, after the time I spent at that, um, Um, the company where I, where I tried to introduce Elm, I, I left there and I was unemployed for a while, and that's when I did like a lot of stuff, um, related to Elm and learned a lot and built complete projects. So I was able to use, um, like all that work that I did built with Elm and all that stuff as, um, as examples of stuff, um, things that I can do with Elm, and that landed me a job at Real Folk.
[00:35:03] Um, so Real Folk is a small consultancy and they mostly work with, um, the, they mostly work with, um, government clients. Drew, drew down is actually the CEO of the company. I think he was a host on, on the podcast previously. And he's really, he's really good at designs and so he meets these these interesting designs and we build them in l.
[00:35:31] Jared: Yeah. So I happened to reach out to Dhruv. Um, I, I know you gave me his contact information, but he had a question, uh, or a, a situation that I could ask you about. So, uh, what that was is he mentioned that you were working on this, this project where you used a JSON alternative for sending data over the, the wire
[00:36:01] in a Lisp-like syntax.
[00:36:03] And this was called MDRN M D R N, MDRN, and here's a little bit of a quote from him and then I'll kind of let you pick up from there.
[00:36:13] He says, "both the Elm and Haskell Parsers were working well until we noticed a strange performance bug where certain payloads were very slow to parse. Dwayne was tasked with finding the root cause and implementing a fix." What do you think is that, is that something that you remember?
[00:36:31] Dwayne: Yeah, I do, I do remember it. It was, uh, it was one of the, the more interesting things that I worked that, that I worked on, um, at Real Folk. Um, so, so MDRN is this experimental project. Um, it's a lot of things, but one of the things that it, that it represents is a data interchange format. And that format, um, is, is Lisp-like, so it has a lot of parens and we use, we use that to structure our data and then send it across the wire.
[00:37:04] And so, uh, our backend was in Haskill, our front end was in Elm. And so both sides needed to be able to pass this data structure. The, the problem appeared on one of our article pages, so, um, the website is, is actually still up. So if you go to DFO website and you go to the blog and you try to open one of the articles, you can open detail tools and look at the network tab and you'd see a request being made, an API endpoint.
[00:37:32] And what's returned is this LIS data structure, and it's a really long, large lisp data structure. Um, so the page was taking like insanely long to load, so like, on the order of minutes, and we couldn't understand why that was happening. So I decided, so I did some debugging and I identified that it was the MDRN parser that was the source of the issue.
[00:37:58] Uh, the
[00:38:00] Jared: a long time. Wow. Yeah. You said minutes that was taking to parse it.
[00:38:04] Dwayne: yes minutes.
[00:38:07] Jared: that, that makes it clear though, right? At least it's not one of those, uh, heisen bugs, you know? It's somewhere in the parser. Okay. So what'd you do then?
[00:38:18] Dwayne: Um, so I, I investigated, uh, I looked into deposit and I saw that it like contained many uses of back trackable. And so I, I knew that could be, um, a source of the performance, um, degradation. Uh, there wasn't any context. Free grammar. 40 40 sites. So typically when people are building uh, parsers with parser Combinators, they, they rarely write, um, context free grammars.
[00:38:47] But, um, I, I, I like to have the context free grammar around as a, as an artifact, understand like what the language is supposed to be. Um, even though it's so easy to write pasta combinators. And so I backed out of the pa uh, a context three grammar and, um, that helped me see that there was like a production, um, of the form.
[00:39:11] Um, so there's data and it can either go to a list or something called a map reference. And a map reference can either be a symbol followed by a dot, followed by another map reference, or a list followed by a dot, followed by a map reference. So it means then that the list could be optionally followed by a dot and a map reference.
[00:39:33] And so that, and when you looked at a code, you saw that that was exactly where back trackable was used. And so back trackable was actually used on when the map reference preference production. So what that means is that it would try to pass the list, then a dot, and then a map preference. And if that fails, then it would try to pass the list.
[00:39:54] So it means if you have a long list, but no. Map reference, so no dot map reference. You'd, um, you'd be passing that multiple times. And so I developed some, um, test cases, of various sizes that just contain these list structures. But no, map references of, of various sizes, 10 ,20, 30, et cetera, constant increments.
[00:40:18] And when you would run the benchmarks on it, you'd see that the, um, that the timing increased by a constant factor. So it just, it showed that the, that the algorithm that we were using was, um, was exponential. And so that was why it was taking, like, on the order of minutes to, to process that. But there's a easy, there's a easy, um, solution to the problem.
[00:40:42] Like. When, when looking at the grammar. So the issue is that there's this common, there's this common, um, prefix on the production and you can use a technical left factoring grammar to remove that common prefix. And you won't have, and when implementing the grammar and using a pasta cator, you don't have to use back trackable there.
[00:41:02] So to give a simple example, a simple example is if you have a production that goes from A to B alpha, B alpha one, or B alpha two or B alpha three, the common prefixes B. And so you can rewrite the grammar to get A going to B, capital A prime. And notice E prime goes to alpha one, alpha two, alpha three.
[00:41:24] And so that removes the common prefix. And when you're implementing deposit gen deposit Combinator, you don't need to use back trackable . To work with it. So I, so I, so I did that and then I re-implemented the parser and, , the, uh, and the, the test cases went from the only order of minutes and seconds to microseconds and then, um, put it on the page and the page load very quickly.
[00:41:51] Jared: Wow. Excellent. So you mentioned a few terms here that, uh, folks might not be, uh, familiar with you. You mentioned, uh, parser, combinators, and Context Free. Could you describe maybe in some, uh, some other terms, uh, what those things mean?
[00:42:09] Dwayne: Sure. So I'll start with grammars.
[00:42:12] Grammars describe languages. And so you, you write, you write a grammar to, um, specify, um, the sets of strings that you want to. To represent, um, in your language. So if you're talking programming languages, the grammars just specify what the syntax of that language would be. And, um, for the computer to be able to recognize your language when it's, when it's parsing the, um, syntax of your language.
[00:42:51] you can write something called a recursive descent parser. So you take your production and for each production you write function that, , that pauses that part of the grammar. And long ago, uh, people came up with the idea of abstracting that recursive descent parser using high order functions.
[00:43:13] And so now, parser Combinators are a means of implementing a recursive, descent parser but, um, using function composition.
[00:43:25] Jared: Excellent. Yeah. Thank you. That makes more sense. And so the reason that you were doing this is because this was a syntax. This, uh, data interchange MDRN
[00:43:39] that you're using was not something that, um, already had an implementation in the language, right? It's not like json where, where folks would be familiar and, and already have, uh, a set of tools that work with that and understand the syntax.
[00:43:54] Dwayne: Mm-hmm. Yes.
[00:43:55] Jared: makes sense. That, that's a pretty. Interesting. , problem, and this was one that I guess you all created, this, uh, this syntax. The MDRN is, is that something that you had discovered or something that your team built this syntax MDRN.
[00:44:15] Dwayne: Sure. Yeah. So, so MDRNa is actually the brain child brainchild of Drew. Um, he created it. Um, so it was there before I got there. The data format itself, um, is supposed to allow you or to be easier to, , to pass data between. between backend and front end. Um, one of the nice features, it, it has, it has like good support for, for numbers, , for large numbers and for rational numbers and all that.
[00:44:43] So you can pause your numbers precisely, um, between backend and, and front end without losing information. Um, I think he, he also wrote, um, a binary representation of the format as well. And so it's supposed to, , allow you to use smaller payloads when sending your data across.
[00:45:02] Jared: Okay. Yeah, that makes sense. And because I have a little bit of knowledge about, uh, some of the projects that you all work on, um, I know why having, , uh, being able to represent large, uh, numbers would be important. But could you describe, uh, kind of what projects might have led to using, uh, a syntax like MDRN where you would be able to, uh, to do that?
[00:45:28] Dwayne: Sure. So the, the project itself is, is experimental. So, there, like these were ideas that Drew was experimenting with, uh, for. For over a year. Um, I don't think he, there was any concrete project that he ever used it on, but I know in the past there would've been projects that would have benefited from having that ability.
[00:45:56] And so it was something he wanted to explore. I know for example, when, when I was working on a point of sale application, um, and we would pass JSON, um, across the wire, we had to, um, represent it as Um, as strings or if we were passing floating point values across, we, um, when you pass the floating point, um, number across, there's a possibility for the loss of precision and stuff like that.
[00:46:23] And so in, in that case, it would've been nice to have a format where you can just represent the number precisely, uh, and send it to the, send it to the client. So there's nothing concrete that I I that we ever used it, used it on, but it was like a thought experiment to see like, uh, if this would, would be useful.
[00:46:44] Make sense, and like how we would go about it.
[00:46:47] Jared: Okay, and so I've been maybe making an assumption here, but you all work on a project called Qoda, and my thought was that this data interchange format would be useful for that project. Is that so? Or do you use it on that or not?
[00:47:05] Dwayne: Yeah, we, we do work on a project called Qoda. And so just to get some context as to what Qoda is, um, it's a decentralized application that, um, allows you to use the blockchain to do borrowing and lending. Um, you can borrow, lend, um, at a fixed interest rate for a fixed period of time, and you can borrow any, um, Types of alternative, um, cryptocurrencies that you want.
[00:47:32] Um, so yes, it does make sense that we, we use it on that, but we what unfortunately, um, due to like the requirements of the project and the time constraints that we, that we had, we didn't, because since MDRN is, is experimental, we didn't want to use use that. It wasn't like production ready as yet. So, so that's why we tried it out on, on folk website, which is, which is fine.
[00:47:54] And we tried out on a few other small projects, which is fine, but we didn't want to try it out on, on Qoda as yet, um, because of time constraints and, and stuff like that. So it's, it's not used there.
[00:48:05] Jared: Okay. Well, yeah, that's, that's what happens when I make an assumption. Um, um, so what, uh, format do you use? How do you, uh, how do you talk with, I, I know it's decentralized, so I guess not with a server or a single server, but how do you talk with. Whatever you need to talk with.
[00:48:26] Dwayne: Yeah. Yeah, that's a good question. Um, so Qoda is built on, on the Moonbeam Network. Um, so to keep things short, it's, it's an Ethereum compatible network. So if, uh, most, most people would've heard of Ethereum as opposed to to moonbeam, but it's Ethereum compatible, which means that the APIs to access the blockchain are similar.
[00:48:52] And so the way we we communicate with the blockchain is through a JavaScript framework called Ethos js. And our Elm application communicates the ethos GS js over ports, and JS interacts with the, with our wallet called meta mask and with, um, the, with the Moonbeam network. There is a, there is a backend, a very small backend to cash data that is written in Haskell, and for that we, we use jsun to, to, um, the send data across, but it's like very minimal in, in its usage of the backend.
[00:49:36] Jared: Sure. Okay. So you're using, uh, Moonbeam, which is built on Ethereum and Moonbeam. Is that something that is built by you all by a real folk or is that, uh, something that you've, uh, borrowed that you're using, that someone else built?
[00:49:57] Dwayne: Yeah, so Moonbeam is, it's not based on Ethereum, it's a separate network, but the API that it exposes is similar to, to the API that gets exposed on the, on the Ethereum network. Moonbeam is a separate project. Um, built, um, by blockchain developers in a different ecosystem. So we have nothing really to do, um, with moonbeam, but external parties can build applications that, that use the network.
[00:50:30] And so where one of those external applications using the network.
[00:50:35] Jared: Okay. Interesting. Yeah, this is a, a world that is pretty much unknown to me, so I may be asking weird questions. Uh, so please excuse me,
[00:50:45] Dwayne: Yeah, no worries. Because I, I just recently got into to blockchain development as well,
[00:50:51] Jared: Okay. Yeah. So, uh, speaking of how you interact with us using the ethers js, um, JavaScript library, you recently posted on discourse, uh, about how you, uh, do use ports. Uh, would you, of course, we can put a link in the show notes about that, but would you, uh, tell us a little bit about, um, how that's working out for you?
[00:51:17] Dwayne: You Sure? so the way it works in. Any blockchain ecosystem is that the blockchain is supposed to be the, the source of truth. So it stores the data. It's, it's supposed to be the one that handles the business logic. And so you write that business logic using smart contracts and, and stuff like that. And to interact with the smart contracts, we, we need to use ether's js.
[00:51:45] So, um, the smart contract has like all the business logic in it, so it has a lot of functions that you need to call in order to process that, to process that data and to
[00:51:56] and to work with the blockchain. Our user interface is, is just a user interface and it, it needs to just coordinate the actions of the user to call the appropriate functions. Any smart contract so the writing gets, gets done on the blockchain. So in order to, um, if we were to write it in a naive way, it means that every interaction that a user makes, we would need to have one port for, for that interaction.
[00:52:28] And so we would end up with 200 plus ports because there's a lot of variation in the interactions and there's a lot of functions that we, that we do need to call. And it's all happening on the JavaScript side. And Evan wrote a long time ago in the Elm Guide, um, as a suggestion that, um, two ports at most, two ports is all you need.
[00:52:50] So I decided to, to take that, to heat that advice and try it out. And, um, just describe the messages that we want to pass over the ports instead. Right. So we, we te um, over the port, we just described the function that we want to call. So we describe the function signator. This is the function. This, the, this is the data that we want to pass as arguments and we pass that through the ports.
[00:53:14] So we just have two ports. We have one port to send information from, um, to JavaScript and one port to receive whatever data, um, that we want to receive. It's not a synchronous um, process. We just send the data and we don't really care what we get back, but we, when we get back data, we know how to deal with it.
[00:53:32] And so it's just, uh, We send messages to those ports. Um, stuff happens on the blockchain and we get data back on it. It does stuff in the ui.
[00:53:42] Jared: And so the benefits of of reducing the number of, of JavaScript calls is you have this one place where, you know, any interaction, any interop with JavaScript, um, is coming through there. Yeah, I like that, uh, approach as well. Um, and. so it ultimately goes through this single port module. Um, do you do anything to make that interaction nicer on the Elm side so that you know, each time you call it, you know, maybe you have a, a data type that then will convert from that standard, an Elm to the J S O N that you would encode to be passed across the port, anything like that?
[00:54:28] Dwayne: Yes. Um, so every, every interaction between Elm and JavaScript is, um, abstracted as a separate module. And so that module handles like what the message would be, how to decode that message, how to encode the message, and whatever other data structures that we need to. To properly represent that data so we can just look in one directory at, um, and see all the possible interactions we can have with each JavaScript side.
[00:55:04] Jared: Nice. Yeah. Yeah. We follow a similar pattern too. I'm glad that you shared that. I've been thinking about sharing that, uh, process that we use, um, as well. But, um, but you've, uh, beat me to it, so I appreciate you, um, taking the time to do that. I think it's, um, it's really helpful because a lot of folks seem to get kind of hung up on how to do that JavaScript interaction and, and you know, and kind of make a big deal about what it is.
[00:55:31] But, um, I found it to be pretty nice. Um, so, uh, I think when you structure it in, uh, in such a way that you're not kind of scrambling around to figure out where the interactions occur, and you have nice, uh, APIs built around that in these kind of, uh, modules that we've done, like it'd be port slash. You know, module name, um, for each of the different interactions, but it then calls the port, you know, the standard ports module, um, to actually make the call Then, um, yeah, it works out really well.
[00:56:07] So, yeah. That's really cool.
[00:56:09] Dwayne: Um, it's, yeah, you know, it's really nice how, how that worked out because I, I never had to use sports in to that extent before. And like in the Elm community, there's, or when people first get introduced to Elm and you tell them that the JavaScript interop um, is such that you have to use this new idea called ports.
[00:56:29] Like, people, uh, get to dis dislike Elm a little bit for that, and they think that it's restricting them. But up to this point, we have had no restrictions with regards to ports and so it was nice to see that it was an elegant solution.
[00:56:49] Jared: Yeah, that's, thank you for saying that. I think you're right. I think the, the thing that sometimes, uh, people think is, well, how do I use, you know, library X, y, z from the JavaScript, uh, ecosystem in Elm if I can't directly talk to it, right? There's no direct FFI or foreign function interface to it. Um, and so.
[00:57:13] Jared: Um, if you're kind of tied in into that particular library that you're using, uh, you may think, oh, well I cannot use it. Right? But you can still use those libraries. You just have to think a little bit differently about it, right? Because everything that goes into, uh, JavaScript land, we have to assume may never come back, right?
[00:57:32] Because, you know, it could fail. Um, you know, there, there could be side effects. It, you know, you could make a request for something and, and never get anything back. So you just structure it in that way of, of sending messages out and maybe, you know, giving a return address if you are expecting something back.
[00:57:47] And, and when you, you kind of change your mind to think about it in that way, uh, the same way you would think about making an HTTP request. Um, then I think, uh, it kind of, for me anyway, it's, it clicked and I thought, oh, okay. Um, now. I can just, you know, just consider it to be the same way I would do any other command and, and go through the Elm runtime, the Elm architecture and, uh, and life's great.
[00:58:16] So,
[00:58:17] Dwayne: Yeah, agreed.
[00:58:19] Jared: so, okay. You have, have been working at Real Folk and you've been working on this project, Qoda. Is that a project that, uh, it's not a contract, right? This is a, a product that you all are building as a, as a product yourselves. Right?
[00:58:36] Dwayne: Yes. Yes, exactly. So it's not, it's, um, so I worked for Real folk for, um, for about a year, and then we, we got an opportunity to, to, um, do something with the blockchain. My CEO and CTO, they are, they have a background in finance and so they spun off this separate company to, to actually do Qoda.
[00:58:59] So it's not necessarily real folk doing it, but yeah.
[00:59:02] Jared: Yeah, the same folks,
[00:59:04] Dwayne: But
[00:59:04] Jared: not the real folk folks. Yeah.
[00:59:06] Dwayne: Yeah.
[00:59:08] Jared: Awesome. Yes.
[00:59:10] Jared: And so you recently created this Elm natural, uh, package in Elm. Um, would you tell us about what problems that solve for you?
[00:59:19] Dwayne: Sure.
[00:59:20] Yeah. So as I continue to use our new, new challenges come up. So one of the things that we, uh, we, we use a lot at, um, on, on the Qoda project is the, is the bigint library, which was written by, um, Coury Ditch, I believe. And so we used that extensively and I, I just wanted to understand better how that worked. Um, I always had a fascination with big numbers and like how to implement them on your computer and stuff like that.
[00:59:50] So I decided as a little side project, I would, I would try to recreate that library from the ground up, up. I separated the big number implementation into Elm Natural, Elm Integer and Elm Rational. And so Elm Natural is like the first, um, version of this thing that just represents natural numbers using an arbitrary amount of memory, whatever it's needed to work with, um, with these numbers.
[01:00:22] And it was just a site project to see how to, how to structure such a code base and how to implement the algorithms because, you know, I like working with algorithms and it's just a fun site project. There's no, there's no major goal fail as yet, but it could be used as the foundation of more libraries, um, that I can build on, for the, for Ethereum based blockchains.
[01:00:51] So, so that's the possibility, but it's not necessarily the, it's not necessarily a goal, it's just for fun.
[01:00:58] Jared: So. Your l Natural project is not a, a tool that you're, you're planning on necessarily using, um, in production. It's, it's about understanding how these numbers work and do you recommend using bigint still for this, or, or do you think that maybe, you know, maybe if, if folks have a subset of problems that they should use your PRO package or what are your recommendations there?
[01:01:24] Dwayne: Sure. So l Natural just represents the natural number. So you, you can represent any natural number from zero to however large you want . once the memory is able to, uh, to represent it. Um, but the big end library represents integers, basically. And so if, if you're working on a project where you need to represent negative numbers, um, which is probably the majority of the keys, then Elm Natural might not be for you, but there's Elm integer that that might be coming along where, um, maybe when I, when I, uh, release that project, um, then I'd say that's, that's a project that, um, many people would, might be able to use.
[01:02:06] Jared: Okay. Excellent. So yeah, we'll look forward to hearing about that
[01:02:12] Jared: And so I, uh, I have one thing that you had posted on discourse, um, and I wanted to share it with you. It was about this article by Cal Newport on Beethoven and the Gifts of Silence. And this is you quoting Cal Newport.
[01:02:29] So, Cal Newport says, "in our current techno cultural moment, we're constantly connected to a humming online hive mind of takes and urgency and quantified influence. Sometimes it seems there's long-term advantage in removing society's soundtrack from your ears, even if in the moment the absence is acute. As Beethoven so vividly demonstrates, you can't really hear yourself until you're able to turn down the volume on everyone else." And then, uh, quoting you after this says, "consider how different Elm would be if Evan didn't intentionally work the way he does." And, and that's it. I thought that was a really beautiful thing that you shared there.
[01:03:11] So, um, did you have any comments about that or, or not?
[01:03:16] Dwayne: Sure I can comment on it. Um, well, first of all, it's a, it's a beautiful quote and I appreciate, um, the ideas that, um, Cal Newport shares. Um, I like, he's a author and an academic, um, as a writer. He writes, um, tons of books on productivity and on, um, the impact of technology on society. But, um, his books like have really helped me shape my career and move in the direction that I'm currently moving.
[01:03:48] Um, so for example, he famously wrote, um, Deep Work and Digital Minimalism. And so it helped me to, um, like reduce the noise from social media and, um, Slack and really focus on what I wanted to do. And it's one of the reasons I'm able to like, work on so many different projects and like really focus my attention and become as productive that I, uh, that I've become.
[01:04:23] Jared: Yeah, I think that's great. I, when I have read about, I haven't read all of those books, but I've, you know, read, uh, bits of them and, and kind of gathered knowledge about Cal Newport's work. And whenever I, I see that, you know, the, the title, uh, Digital Minimalism, I think about Evan. And so, um, I thought it was great that you made that connection as well, um, and shared that.
[01:04:50] Jared: So, uh, is there, um, I think really, I, I don't have any other questions, um, written out for you. Do, is there anything else that you wanted to share before we get to pics?
[01:05:01] Dwayne: Uh, no, I think we can move ahead to picks. There's, there's nothing else I think I need to share.
[01:05:09] Jared: Okay. All right. Well, what picks do you have for us?
[01:05:13] Dwayne: Sure. So, the first one was, was SICP. So, as I mentioned, um, SICP was my introduction to functional programming, though it, it can be, um, a complicated read. I think, it is a necessary read and it would help you a lot with functional programming, and if that book is too complicated, then there was, , a, a book called How to Design Programs that, um, goes through the same concepts as SICP, but the pedagogy is, is much different.
[01:05:43] And so it uses better examples to explain those concepts. The other pick I had was, was actually was actually Cal Newport and, and his books like it really helped me and, um, you can read them and gain some insight from it. So, um, some of, some of those books include, um, So Good They Can't Ignore You, Deep Work, Digital Minimalism, and A World Without Email.
[01:06:08] I think A World Without Email like really represents the way Evan works. And so if you read that book, you'd get an, a better understanding of how he works and, and why he works that way. At least that's my opinion. And like I've been really into programming languages recently and, um, the book Essentials of Programming Languages has helped me to understand how to implement various programming features and also translate those ideas into my day-to-day job. So it talks about, um, like continuations and continuation parts style and team reclusion and stuff like that. And so I think, it can really add value to especially functional programmers. So those would be my, my three picks.
[01:06:57] Jared: Excellent. Yeah. So this Essentials of Programming Languages who's the author of that.
[01:07:02] Dwayne: Um, Dan Friedman and Mitch Wand.
[01:07:06] Jared: All right. So I'll add some links to these in the show notes. Uh, did you have any other picks for us?
[01:07:14] Dwayne: Um, no, that's it.
[01:07:16] Jared: Okay, so I just have one pick today and that is, since we we're talking about ports, I thought, , the, the former host of Elm Town, the original host Murphy Randle, gave a talk at, uh, elm-conf 2017, The Importance of Ports. um, I'll, I'll add a link to that as well. But I thought, um, that really kind of fits into, uh, our conversation about ports there. And that's it. Well, thanks Dwayne for your time for coming to Elm Town. Until next time. Goodbye.
[01:07:47] Dwayne: Thanks. Thanks, Jared. Thanks for having me.