 Welcome. This is Shipping of Production Web FNL. I'm Richard Feldman. And one of the interesting things about this conference is that people come here for a lot of different reasons. People are excited about a lot of different things. People come to functional programming for a lot of different reasons. Some people are excited about the math aspect. Some people are excited about the abstractions. Me personally, I'm excited about building things. I like building great user interfaces, great user experiences. Very few things give me as much joy as just watching someone use something that I've built and it puts a smile on their face. That's what I love doing. So I end up with sort of elaborate things like this. You know, polishing and tweaking and making sure everything's just right. And what leads me to functional programming is the fact that it's so easy to shoot for something like this and end up with this. Right? It's software, right? Software is error prone. In short, I come to functional programming because I just want my code to stop breaking all the time. And somewhat recently, as in several years ago, I had an experience that really drove this home. And it was in the course of building this. This is DreamWriter. This is something that I wrote back in 2011, so I like to write novels in my spare time. And I had this interesting experience where I was like, I'm going to put this on Google Docs and get syncing and all these nice things. And so I uploaded my 100,000 words to Google Docs and it died. Like, literally the browser tab died. It was like, aw snap. What are you doing? I was like, well, that's no good. So I looked at some of the alternatives out there and I couldn't really find anything that was just what I wanted. So I said, okay, look, I know how to write JavaScript. I'm just going to build something for myself. I'm going to scratch my own itch. So I did. And I put it together and it didn't look like this. This is the result of a good deal of iteration. So I ended up with this sort of, I wanted to write everything in the middle, but I still wanted to have this sort of chapter-centric notion of things where I could click around. And if I edited something, hello everyone, it would update the outline in real time. I could add a chapter really easily. I wanted everything to work offline, which this does. So I can turn off my wireless and have it still come up. I can, you know, open new tabs. And it's remembering my changes. And in fact, it's doing this even offline. It's just storing this in the browser. There's actually no server behind this because I wanted to be able to write on airplanes. I wanted a distraction-free writing mode where I could just fade out everything with the words in front of me and be able to only fade back in the UI situationally. And so you might be wondering, okay, well, what does this have to do with functional programming? Do you end up with this, you know, UX problem and arrive at functional programming? And the answer has to do with the architecture of the original version of DreamWriter. And what I used for that is GMOGE, which is, you know, kind of a pretty standard, like, fairly well-understood, well-used, seems to be pretty popular. Oh, if you're not familiar, GMOGE is short for giant imperative mess of jQuery. Very popular, right? Very, very well known. So to be fair, when I started off, it was just imperative jQuery. It wasn't a giant mess until I did all this iteration. And I tried out this thing that I'd built and found, oh, no, no, I can't do it that way. I gotta change this. Oh, no, no, this is all wrong. I gotta reintroduce that. And, you know, you do that and you accumulate technical debt and eventually things kind of get out of hand and what you end up with is a giant mess. At one point, I knew things were really bad because I broke paste. I couldn't paste things anymore. Which, if you're writing, you want to do. And so, at first, I was like, okay, well, I broke paste, but whatever, I'll fix it. So I went in my code and I found the problem and I fixed it. And then that created another problem that was actually even worse. And I was like, okay, wait, you know, I'm just gonna back off, gonna revert those commits and just pretend that never happened. I'm just gonna try again. So I tried a different approach to fixing paste so it would stop throwing a runtime exception and preventing paste from happening. And it broke a different set of things. And I was like, oh man, okay. You know what? Forget it. I don't need first-class paste. I've got this whole DOM right here. I'm just gonna use inspect element and copy the text out of one DOM node. And then go in and paste it. I was really doing this. Paste it in another DOM node. I don't know what's sadder. The fact that I was actually doing this or the fact that this was still somehow overall a better user experience than Google Docs at the time. But at any rate, when I kind of looked in the mirror and I was like, okay, I need to have an intervention here. I was like, self, you need to rewrite this thing. This is not sustainable. This is no way to live. What are you doing? You need to fix this. So I said, okay, I'm gonna rewrite this. How? How do I rewrite this such that this doesn't happen again? So I don't end up with this giant mess so that I start with something that's clean, but over time it no longer deteriorates into this. And a simplistic answer is just write a whole bunch more tests. But in my experience, that's not quite the answer. It's not the panacea that we've often been led to believe. But I did, between when I started, when I wrote the first version of this and when I started thinking about, okay, I need to rewrite this, I did see something that had a profound impact on me, which was this talk. Simple Made Easy by Rich Hickey. Show of hands, anyone seen this talk? Awesome. Okay, so for the few who haven't, you should definitely check this talk out. I've been programming since I was nine, and this talk changed the way that I looked at programming forever. And one of the things that he talks about in this is this notion that simple by his definition is an objective notion. You can say that something is this simple or this complex. You can compare two things and objectively say, this one is simpler than this one, or this is conversely more complex than the other one. And that's because according to his definition, the difference between simple and complex has to do with how things in a system are interleaved, how they relate to one another and whether or not they are coupled. So if you have a bunch of different things going on in your system, but they can be considered independently and they're not interleaved. They do not depend on one another. You can just sort of zoom in to one of those and say, I can think about this. I can just put this in my head and think about it and change it and not have to worry about it exploding into all these other side effects that I hadn't considered and impacting all these other things in the system. Then that's a pretty simple system. Obviously this is not what I had with my pace bug. What I had with my pace bug was the symptoms of a system that is very complex, where one thing is tightly coupled to another thing, which is tightly coupled to another thing, such that when I fix this one thing, it breaks all these other things because there are just so many unexpected side effects and consequences of changing one thing. And one of the problems with this being an objective notion is that you sort of can't get so much better that you escape human biology. At some point there's only so much we can keep in our heads and with a really complex system, when you have all these dependencies and all these things tightly coupled together, the only way you can fix something and be sure that it's not actually breaking other things is to load that entire system into your head. And once the system gets so complex that it no longer fits in a human head, you're in the mess that I was in. And there's no way out of it. So on the flip side, so the talk is simple, made easy, Rich Hickey also gives a definition of easy versus difficult, which is different. So easy versus difficult is subjective. It's to the individual. It has to do with familiarity. If something is easy for you, it might be difficult for me or vice versa. Functional programming might be easy to someone because it's near to their current skill set, but it's not easy for me because it's not near to my current skill set. So simple is less interleaving of concepts and easy is nearer to your current skill set. And so the question becomes, what can this do to help me solve this problem I'm having, where my code base is no longer something that I can work with? Is this a notion that I can use to make things better the second time around, such that the next version of this that I write doesn't devolve into this problem that I saw? Well, one thing that's true is that familiarity grows over time. So if I adopt some new paradigm, some new way of doing things, I can become familiar with it. There's no biological restriction there, right? I can learn something new. I can learn a new technique that will perhaps allow my program to be simpler. If I learned it, that's it. Now my program gets to be simpler. I get to reap the benefits of that and now I can consider parts of my program in isolation in a way that I couldn't before and that would fix the problem I've been having. Complexity, on the other hand, is forever. If something is too complex, it's always going to be too complex no matter how much you learn. And simpler code, of course, is more maintainable. Any time you can zoom in and sort of say, okay, I've got this problem, I want to just look at the isolated part of that problem and there's some other thing that needs to be fixed, but I can look at that in isolation as well. I'm going to have a better time of things. I'm not going to have this problem where complexity builds and builds and builds and you can no longer keep it all in your head. So I've determined, okay, I want simpler code. I'm intrigued, I'm interested. This seems like, you know, I'm not sure exactly where this is going yet, but it sounds like it has sort of the shape of the solution to the problem I had before. Okay, so how do we put this into practice? What is the concrete takeaway here? Stateless functions minimize interleaving. So stateless, aka pure functions, aka referential transparency. I like stateless just because it's descriptive, but the basic idea is you have a function and all it does is it looks at its arguments and it returns a value. That's it. It has no side effects and it doesn't look at anything in the outside world. It just looks at its arguments and it just returns a value. So one implication of that is that if you call a stateless function passing the same arguments, it always returns the same value no matter what and has no other side effects. So what's cool about these is that their dependencies are very clear. Their dependencies are only the things that are passed in and they have no external, they create no external dependencies. They don't affect other parts of your program. So the more of these that you use, the more chunks of simpleness you have in your program. Anytime you have a bug in a stateless function, you no longer have to worry about loading this whole big portion of program code into your head. You can just look at that one function and figure out where the bug is. Cool. So I'm still working in CoffeeScript. I've still got this jQuery based code base. But for my rewrite, I'm saying, okay cool, I'm going to start writing in more of a functional style. I'm going to start using stateless functions more, try and use it for as much of my logic as I can and just see where that gets me. So I did and as I was going along, things were getting better. I noticed that I was getting fewer bugs in the code that I tended to write. And then React.js came out, which was great, and Flux came out with it. And this let me move a lot of my rendering logic into effectively stateless functions. Granted, yes, in React there's a little bit more ceremony than just a straight function taking arguments and returning something, but the basic idea behind React is essentially boils down to a stateless function. You have this render function that has some arguments that come in, and all it does is it returns this virtual DOM representation of how you want the page to look. And then what React does behind the scenes is it diffs that very quickly and efficiently against the previous virtual DOM that you showed it, and it figures out the minimal set of updates to make to the real DOM in order to effect having that change be displayed on the screen. So it lets you move all of this imperative jQuery stuff that's destructively updating DOM in real time into stateless functions. Flux is an architecture that goes with this and has a lot of similar characteristics where you get to do more with stateless functions. So this is great. I started adopting this. I started using it at work, and I said, okay, cool. I'm going to start rewriting Dreamwriter in this, and I made some good progress doing that, and I got to a certain point where I was like, you know what, this is excellent, but let me take a step back and think about this for a second because now I'm curious. I'm curious how far down this rabbit hole I can go because I still would, from time to time, get a bug that was the result of sort of accidental mutation or accidental side effects where I'm trying to write stateless functions, but just as a fact of the world in which I'm writing these things, sometimes I would accidentally do that, and then that would be a difficult bug to track down because I'd been sort of in my head thinking, okay, well, these are not the types of things I need to worry about anymore because I'm writing in this style. Or even worse, I would have a third-party library that would not respect these invariants. So it would actually mutate something, or it would have a side effect that I didn't realize. So I wouldn't get these bugs super often, but when I did get them, they were a pain to track down. I was like, is there something better? And more to the point, is there something better where if I were to embrace this, like let's say at a language level, could I actually get more benefits because that would unlock certain APIs that don't work when you have to have the assumption that your language can mutate things and so forth like I did in CoffeeScript? I was like, okay, cool. And kind of what I realized is that I'd been using Discipline to do functional programming. I'd been sort of saying, okay, great, I'm going to choose not to use this set of features. It's like, you know that book? It's got JavaScript, the good parts, and then JavaScript. We've all seen that picture, right? So you have to use Discipline to get the small book. You have to say, I'm going to choose not to use these things because they've caused problems for me in the past. Invariants, on the other hand, are easy. If you can't use those things, if you can't even reach for them, then you can just put them out of your mind and stop thinking about them. Life becomes easier. So I was like, okay, what I want are some invariants around these things that have been solving these problems for me and making my code less buggy. How can I get a language that increases invariants around immutability and side effects? Or the lack thereof? Well, there are over 200 languages that compile to JavaScript, so I needed to whittle this down pretty quickly if I was going to pick one. So I came up with some deal breakers for me. One is slow-compiled JavaScript. So there are a lot of languages out there that compile to bloated JavaScript. I'm a UX guy. I want to make a nice user interface. I especially want to make a nice user interface for myself. When you're dealing with 100,000 words in the browser, you run into some performance stuff. So that was a deal breaker. I couldn't use anything that had really slow-compiled JavaScript. Pour interop with JavaScript libraries. There's a whole big ecosystem out there of JavaScript stuff, and I do not want to reinvent all those wheels. A concrete example, Dreamwriter has a note system. You add a note, you write in it, and it saves, and it uses a lunar.js so that I can do a full text search on top of that. It takes care of indexing things and stuff, and it all works offline. It's great. Again, not a wheel I want to reinvent. I want to just have that experience where I'm typing in there, and then when I search for the note later, it's just already indexed everything and it just works. So interop, definitely a critical feature. And then the last one was a deal breaker was any language that seemed unlikely to develop a community. So I'd seen languages in the past, especially around compiled to JavaScript, because that's something that so many people want, where the language would crop up and there would be a little bit of buzz and excitement, but then it would kind of taper off and it wouldn't actually end up resulting in anything. So this is a concern because, again, if I'm going to be maintaining this long-term, the last thing I want is for the compiler to be stuck on version 0.0.2, and it's never going to get updated again. So these three deal breakers really helped me narrow it down pretty quickly. The things that it narrowed it down to were sort of the JavaScript but less painful camp. So this is like Dart, TypeScript, and CoffeeScript. So CoffeeScript is what I was already using. I ruled these out basically because, A, if I'm going to stick with something that doesn't have immutability or lack of side effect prevention built in, I might as well stick with CoffeeScript because I've already got that and I'm already familiar with it. So Dart and TypeScript really didn't have anything to offer there, so I kind of ruled them out pretty quickly. And then there were languages that were explicitly functional that had more of these invariants that had immutability and, in some cases, ways to control side effects that could sort of easily talk to JavaScript. Elm, I ruled out almost immediately because this is an Elm talk, by the way, so we're going to come back to that. But I ruled out almost immediately because all of the demos I was looking at, it looked like Elm was doing its own layout stuff instead of CSS, and I already had this big pile of CSS for Styling Dreamwriter. I really didn't want to rewrite all that, so I was like, okay, not going to do that. The main contenders. So at this point, my three options were stick with CoffeeScript, switch to ClosureScript, or switch to PureScript. So ClosureScript has a flourishing community. The Closure community is great. It has trivial JS interop. You just basically call stuff. Super easy. The downside is that side effects and mutation are allowed. So mutation is controlled in ClosureScript, but it is still allowed, so it's not like I could just put it out of my mind entirely. And certainly side effects are allowed everywhere. That's a contender, but let's look at PureScript. So PureScript has 100% immutability everywhere. It has type inference, which is something I was interested in. That wasn't a must for me, but it was interesting to me because I'd come from like a Java and C++ background when I was growing up, and I did a lot of that. And when I switched to a dynamic language, it was so refreshing to not have to be like, this is a string, and this is an int, and this is this parameterized, and this parameterized, and this parameterized. You know, just the verbosity of those type systems had just become really grating to me, and I was really enamored with the idea of just being able to write out my code and just go with it. But of course, over time, I then subsequently realized, oh yeah, there are drawbacks to this, and it would be kind of nice if I had that compiler again that would tell me about my mistakes ahead of time, but without all the verbosity. And so type inference seemed like a good way to do that, especially if you have 100% type inference like PureScript does, where I can just write out whatever expression I want. I don't have to annotate it with types if I don't want to, and then the compiler will still tell me if I mess something up. Seems like the best of both worlds, and I was pretty eager to try that. JavaScript, interop, and PureScript, very straightforward, you just take your JavaScript code, and you add a type signature, and you're done. And then finally, basically, functions cannot have side effects in PureScript. So that's, I put an asterisk there, and I probably should have put an asterisk by immutability, too, because if you look at that second point there, the way the JavaScript interop works is you just take the JavaScript and you add a type signature, which means you can lie if you want. You can be like, I promise this doesn't have any side effects, but it totally does, and I promise this doesn't mutate anything, but it actually does, which, you know, I wouldn't like to think that I would do that to myself, but there is sort of a nagging concern in the back of my head that maybe some third-party library I'm using is doing that. So I was kind of like, alright, that's a little bit annoying, but I bet it's not going to come up very often. Maybe once in a blue moon it's going to cause a bug that's hard to track down, but definitely not a deal-breaker, and definitely way better than what I'm working with now. So I was like, yes, rewriting PureScript. This is my plan. I'm excited. Let's do this. So I immediately went out and was like, okay, cool. The tools that I like to use for rendering now are React and Flux, so I'm going to find out what the analog for that is in PureScript, which turned out to be, oh, there wasn't one. And then I was very sad. So this was, like, now there's Thermite and Halogen and stuff, so you can actually do that, but at the time there was just sort of a repository for a package that was going to, at some point, have React bindings in PureScript. And I followed it and tried to contribute to the discussion, but I was like, I'm kind of new to this. I don't think I'm the right person to be discussing what the API ought to be, because I don't really know how this stuff works yet. So I followed it in weeks and maybe like a month or two, and while I was doing this, being sad about the lack of this in PureScript, a blog post came out. The title of the blog post was Blazing Fast HTML and Elm. And I was like, interesting. That's that thing that I wrote off that had some characteristics that seemed good. And now here's a blog post about how it's now got exactly the thing I was looking for, which is to say a React and Flux style architecture, except this looks way simpler and more awesome than React and Flux, because it's as if the whole language were built around that instead of hacked on top of JavaScript. And then there were these benchmarks in the blog post. And it's like, oh, the Elm one is beating everything else except for Mercury, which is kind of the JavaScript one that just says, let's pretend everything is immutable and assume invariance about that. And if it's not YOLO, which I was like, okay, I'm not going to use that, but Elm actually enforces all of its immutable invariance. And it's doing really well. It's like benchmarking more than twice as fast as React. That's pretty awesome. Okay, okay, I'm interested. Tell me more. So I kind of came back and took a second look at Elm. And I learned how it does JS interop, which is with ports. So basically the way Elm ports work is it sort of treats Elm land and JavaScript land as like a client-server relationship. And they just talk with data, kind of like Erlang message passing. So only raw data is allowed in and out between the two lands. And it has this sort of pub-sub communication system. So for example in that notes example, if I wanted to use lunar.js for my full text index, as I do, the way that would work in Elm is I would have my Elm described search box when the user typed something into the search box and say, okay, cool, here's what the user typed in. We're going to send that as an event out to JavaScript land. It says, the user searched for this string. Over in JavaScript land, it's listening for that and says, oh, got it, the user searched for this string. Hey, lunar, go give me a bunch of search results. So lunar says, cool, here you go, here are your search results. And then JavaScript land broadcasts an event back to Elm land saying, here are the search results. Go ahead and do your re-rendering thing. So what's cool about that is that because only raw data is allowed to cross the boundary and there's not actually any code sharing, this preserves all of those invariants. Actually, all of your Elm code is guaranteed to be immutable. There's no asterisk. It actually is guaranteed that there are no side effects. Pretty cool. So now I'm like, okay, so it's also got all of the things that I liked about PureScript. It's got 100% immutability. It's got 100% type inference. The JS interrupt is a little bit more involved than just slapping a type signature on a thing, granted. But it preserves the invariants, which is nice for my piece of mind and functions have no side effects. What about this thing? You guys seen this, the time-traveling debugger? I was like, what is that? This is what that is. If you haven't seen this, this is a thing that Elm has. This is Mario. Whee. I'm going to run around and jump as Mario. Go around. This is a live code editor here on the left. You can just edit this Elm code, and it's going to update over here. I'm going to hit pause. So now I can actually rewind time, and it's actually just going to replay those user inputs in reverse that I just came up with. So we can see Mario doing that. That's pretty cool. Okay, cool. Here's another thing you can do. You can live edit this code. I'm just going to change gravity here a little bit. It's actually going to keep replaying the user inputs with the new code as I'm changing it in real time. Now I can do this again, and keep replaying the user inputs with the updated code. What's especially cool about this is that this is real. This is not a hypothetical example. I saw Brett Victor talk many years ago of someday in the future, it would be really great if we had something like this. This already exists? What? What is this language? And it's Elm. Yeah, so rewrite an Elm, clearly. So I was like, yeah, all right, let's do this. So to sum up where I'm going is I've started with my original architecture of giant imperative mess of jQuery, and now I have this goal architecture in mind of purely functional Elm. That's what we're going to get. The way what I already had was this sort of rearchitect that was going from jQuery to sort of a functional style coffee script with React and Flux. And I totally didn't intend this, but it actually ended up being a great way to do this. And if you're intending to port some code from imperative to purely functional, I highly recommend doing this rearchitect as an intermediate step. Because effectively what it let me do was it let me anticipate my invariance. So by rewriting a whole bunch of my imperative logic as stateless functions, it basically made it so that once I had all that rearchitected, which I could kind of do piecemeal, then the final translation step, a lot of my stateless functions, I could just port one to one over to Elm, and it was just a syntactic translation. I didn't actually have to rewrite the logic. So it allowed me to split this up into sort of two pieces, the first piece being start from imperative, rewrite to be as functional as possible, and then step two being take that fairly functional code and then port that the rest of the way to a purely functional language. So it allowed me to start from imperative and do both the translation of how to convert and rearchitect while simultaneously transitioning to a new syntax and new compiler, et cetera. I think that would have been a lot harder than the way I did it. Incidentally, if you're curious, both of these are open source, so I open source the coffee script slash react slash flux rewrite, which is tagged at a particular version, and then also the Elm rewrite tagged that feature parity with that version. So you can sort of see side by side the version nor will I ever. So let's look at some Elm code. This is Elm code. This is basically what the right sidebar in DreamWriter looks like, the code behind it. So you can see it looks a lot like the actual DOM structure that's going to end up on the screen. It's fairly straightforward. You've got some divs, they've got some CSS classes which will then be used to style things. We can see in the middle there an element and a span element. Some things to note about this. One is this is not a templating language. This is just plain vanilla Elm code. It just happens to be the case that plain vanilla Elm code is concise enough that you can write some nice DSLs like this pretty easily. So this is going to be Elm syntax 101 if you want to actually dive into Elm. There's a workshop tomorrow which I am now teaching. So come to that. But 101 stuff. So all of these, so that first line is saying we're going to call a function called div and we're going to pass two arguments. So when Elm arguments are not comma separated they're just space separated. So the first argument we're passing to div is a list of attributes which is in that square bracket and the second argument is another list of nested elements, of child elements. So first argument is a list of elements which is just going to be one element which is the result of calling the class function passing the string sidebar which is going to result in an attribute this is a CSS class called sidebar and the second argument to div is a list of child elements all of which work exactly the same way. They just have their functions that take two arguments versus a list of attributes. Second is a list of child elements. So we can see we've got a text input which has a placeholder of search notes so it shows that to the user. It's got an on input handler which we're going to get back to in a second and then the input has no child node so it has an empty set of square brackets which is just the new note button so you can press that to get a new note again on click handler, come back to that and then just the actual body of the sidebar below that. You can see that we're freely interspersing variables in here there's going to be some more code surrounding this so defining things like sidebar body and search notes and so forth but for the sake of the slides and you're being able to read them I've omitted a lot of that and we'll just assume that they're there. Okay, so this on input thing let's go into that a little bit and what I've said about Elm is that there are no side effects anywhere and everything's immutable so a question you might be asking is how do we set up event handlers? In JavaScript the way we would do this is we would imperatively say add event listener and then that would take a callback that has a side effect that would do something but there's no such thing as any of that stuff in Elm you can't destructively update DOM elements and you certainly can't have callbacks with side effects so how do we do that and is that annoying or awesome? Spoiler alert, it's awesome. But first things first how do we actually do that in a language that has these invariants? So let's just go through this step by step and I'm going to write out some sort of JavaScripty pseudo code this is not an exact translation of the Elm code it's just to sort of give you an idea in a language you already know well, presumably what's going on here so let's first look at the on input part of this so remember that this is just a function call we're calling a function called on input passing two arguments search notes and target value those are the two arguments the on input function and this is going to define an event handler so this roughly corresponds to the add event listener thing in JavaScript so it's saying whenever there is an input event we want to do something which we'll get to momentarily the input event if you're not familiar with it is kind of like key up or key press except it's got some extra cases so this is if someone types in the search box or they paste into the search box any of that kind of stuff those will trigger an input event immediately not just when it loses focus but as soon as they type the key so we're saying every time the user does something to that search notes text box we want to do something next I'm going to jump to the last one and target value because this is extremely straightforward all it does is it extracts event.target.value because that's what we care about in this case event.target.value is going to have the string that the user typed in that's what we want them to be searching for we want to pull that out of the event so we don't have to go look it up in the DOM we want to just get it right there so putting those two together we've now said whenever there's an input we want to take that input event and pull out event.target.value that string that the user has typed into the search box and now we're finally going to use that string to search the notes search notes how does this work so this is the interesting part this is the part that's unusual versus easy this is something that's probably unfamiliar it's something you can learn and it actually is quite simple but it's probably farther away from your current skill set if what you're used to is imperative JavaScript basically what this is doing and again this is just sort of JavaScript pseudo code and this actually looks a bit different but basically what it's doing is it's a function that takes that query string that we've extracted out of the event using target value and all it does is it returns a description of an action that's going to update our application state and so there are three components to this one is sort of what action we want to take so in this case this is going to be a search notes action which I've represented as a string here just saying search notes so later on somewhere else in our logic we can be looking for that string and say oh whenever we see a search notes action we want to update the application state in these various ways there's a payload which is sort of the parameter that goes with that action in this case it's the query string that we're actually searching for and finally there's the destination and this is the critical part that makes Elm different from other languages I've used action signal what is that so Elm programs are basically built up of these things called signals a signal is just a value that changes over time so you can define signals for whatever you want in this case we're going to be defining an action signal and so basically for most of your program the action signal is going to have a value of no op it's not going to do anything because there's no user input most of the time we can take a given point in time and say what action is being taken right now the answer is nothing the user is not clicking anything they're just looking at your screen but we can send things to this action signal and change that value at different points based on user input so what all of this is doing in aggregate is we're saying whatever the user does an input we want to change the value of that action signal to stick in that search notes action that's going to describe this is what we want to have done based on that user input so in effect what we've done is we've now translated completely declaratively without mutating anything a description of sorry the user input to a description of the action that's going to update our application state based on that and so now elsewhere in our program we can just pick up on that Elm has lots of features for working with signals and doing various things based on signals none of which violate these invariance and which is probably a deeper discussion than I have time to get into here suffice it to say that all of these components just given this description of I want to send this data to this signal you can successfully model an entire UI and that's exactly how DreamWriter works all that stuff you saw earlier that's the Elm version of DreamWriter all that interaction that I was going through earlier that's all done using signals in this same way and so on the one hand this is probably unfamiliar it's kind of weird to be having an on input handler that is just returning data instead of actually performing a side effect but on the other hand I mean look at that code up there like how complicated is that it's just on input search notes target value yeah those are doing unusual things but when you actually get used to it which doesn't take all that long to be honest just sort of you know copying pasting that stuff around and changing it based on the interactions you want to have happen it's pretty easy it's pretty straight forward but I said earlier there's actually something really cool about this and there is so let's look at this again so we have two handlers set up here and new note as previously mentioned Elm is all stateless functions which means that every single function in Elm is only allowed to look at its arguments to figure out what it's doing what it's returning it's not allowed to look at outside state of any kind so that implies that again there's we're pretending that there's more code up above so search notes and new note are each using signals right they're going to be saying we're going to describe some actions that are going to be sent to signals now suppose they weren't using the same signal what if I had two different signals one for searching notes and one for new note and each of those got passed in a different signal what would that mean so then later on somewhere else in the program it's going to combine the two and update the application state in the same way but if I actually split that up into two signals what would that mean what that would mean is that now later on let's pretend I have a bug where I'm working along and suddenly a new note pops up and I'm like what is that to happen that's totally wrong the next question on my mind is okay who did it like who's the culprit who's to blame where is this bug coming from when you're explicitly passing signals around like this I can rule out like 90% way more than 90% of my program because literally only functions that have access to that particular signal can possibly have been responsible because there are no side effects nobody else can possibly have anything to do with that they can't even touch it they're not even capable of touching it so all of my render logic for let's say the left sidebar if I want to know if the left sidebar shouldn't have anything to do with searching notes searching notes is all in the right sidebar if I want to know whether or not anything in the left sidebar could possibly be a culprit all I gotta do is look for that signal figure out if anybody's touching it okay move on I know the bug can't be there because it literally doesn't have access to it and you can do this with your whole program you can control over where effects are allowed to happen and who can possibly be responsible for things and it makes debugging really awesome so how was it how was this experience I mean this is a lot of new stuff I've been getting into the functional thing this is my first sort of plunge into a pure functional environment I didn't really know how things were going to go how was it it was so great oh man yeah so first thing the performance was ridiculous I've done some performance optimization of my time I've rolled up my sleeves and gotten out the flame graphs and spent more than days on things here's the experience I had in Elm so again everything is stateless functions and immutable data and if you pass a stateless function the same arguments you definitely get the same return value which implies that everything in Elm is cacheable if you get the same function with the same arguments you don't need to bother running it again you can just return the result that you cached earlier you can do that everywhere that's kind of cool so I ran into this problem reasonably early on where I had built up my whole UI and it was actually with search notes where I was typing in to search the notes and I was noticing oh this is kind of laggy like I can see the characters come up one at a time and I was like okay why is that like I hope I don't have to get out the flame graphs already but I was like okay well let's see every time I type a character on input fires and then it's going through and running the render logic for my entire application right it's going to re-render the left sidebar the right sidebar and the editor all that logic yeah it's just rendering virtual DOM nodes but it still has to go through all the logic to figure out which virtual DOM nodes to show that's a lot of code being run for every single keystroke when all it needs to be doing is just updating the search box and like going and getting search results I was like hmm what can I do about this so I looked it up and it turns out that Elm has a function called lazy which allows you to be lazy and what it does is exactly what I said earlier it caches things so you just instead of calling this function say like render and then you give it two arguments you call lazy passing the render function in two arguments and lazy just takes care of caching it if it sees the same call with the same results then it caches it if not then it runs the function then caches the result very straightforward so I was like okay let me sprinkle this around I use this like put one here put on the left sidebar put one on the editor put one here it's perfect lightning fast performance like great I'm used to like spending days on performance optimizations like this and if you think about it it's kind of obvious because after I did that and like you know whatever six lines of code or whatever it was and it's like okay you've pressed a letter time to go update the left sidebar what changed oh nothing changed okay we got that the editor gonna update the whole editor oh nothing changed okay yeah done what about the right sidebar oh only these things changed okay well then we'll just do that but I didn't have to like reorganize my whole application I just literally added like one word in a bunch of different places and boom ridiculous performance fantastic much better than what I'm used to another thing I kind of appreciate about is just language usability so this is actually currently only on the bleeding edge compiler it's not released to the stable version of the compiler yet but I'm excited about it so I'm gonna talk about it basically recently there's been a push to improve the quality of error messages check this out so this is the error you get when you have a type mismatch of any sort in this particular case it's you have a list that has mixed values in it so elm lists they all have to have either numbers or strings or whatever the case may be they all have to be the same type so it's saying okay hey not all elements of this list are the same type of value just FYI notice the mismatch in element number four tells you where it is it's even got a little ASCII squiggle under the offending like part of code and line numbers on the left so you can see exactly where in your text editor this is how awesome is that and then below it gives you I had to cut it off for slide reasons but below that it's going on to say oh yeah by the way these are mostly numbers but there was a string in there and it also goes on to make suggestions in a lot of cases so for other types of errors it'll say oh you did this and it looks like you might have actually meant one of these three things is that one of them it's fantastic refactoring is just the most fun thing because the compiler is just so good at catching errors I've just had this experience over and over where I'll just make this gigantic refactor I'll just break everything this is so far removed from the jQuery days I can't even okay I'm going to break all this and I'm going to say okay compiler tell me what I broke it's like okay you broke this fix that you broke this okay fix that and then when I'm done I bring it up again and it just works with no regressions and this has just happened so often let me show you this this is something I did recently this is some dream writer code this is a reasonable size yeah it's a big diff this is a lot of things that changed I'm just going to keep going here I made some changes changes were made when this was done and I got it to compile which actually didn't take that long believe it or not it just worked with no regressions really that's it that's preposterous like what okay let's move on it's a great experience the craziest part about that is that when I went into that I was like this is going to be nice I'm going to fix all these compiler errors and then it's just going to work with no regressions and then I did and it did and I was like okay cool what kind of world do we live in this is great here's the thing anyone ever use package managers where you update a package and suddenly it breaks your stuff how cool would it be when they were facing API and made a breaking change they had to increment the major revision number that's a real thing and Elm already has it for every single package not only that so you can always upgrade to minor versions and know that your code's guaranteed still going to compile it might break because they introduced a bug so Elm has not yet solved the problem of programmers writing bugs however that's great even better there's actually a diff tool you can just diff two versions of an API just be like hey what changed between 1.1.0 and 2.0.0 of Elm HTML it just says here are all the things that changed here's some new stuff here's some things that changed it just tells you it's fantastic it makes upgrading packages so much nicer than anything I've ever used before one other thing I should mention so I'm a JavaScript developer I encounter runtime exceptions sort of as my default way of finding out when things are not working undefined is not a function raise your hand if you're familiar with undefined is not a function okay yeah we've seen that one before you know where I haven't seen that is in any of my Elm code ever and that might sound like a trick like oh yeah it's cause it's called something else and Elm no it's just that I don't get runtime exceptions let me be explicit about this I have never gotten a single runtime exception from any of my Elm code in all of DreamWriter in any other Elm code that I've ever written any time I do get a runtime exception it's always the fault of some JavaScript coming through a port and the fix has always changed some JavaScript it has never once been to change some Elm because it's just that well designed it's that well put together that compiler just tells you about stuff that's how you can have this excellent refactoring experience it's just everything is put together so well that you just don't get runtime exceptions anymore again preposterous I didn't know I could live like this it's so much better so yeah overall how was it oh it's so great it's my favorite language now and really what it comes down to is that I can now build things that are beautiful and elegant and excellent user experiences that actually stand the test of time that I can then change and maintain easily without having to rewrite in a different language it's just way better across the board and I think really responsible for this is the simple fact that of all the languages I've ever used Elm was the simplest yeah it was unfamiliar at first it had a lot of new concepts for me to pick up they were not close to my current skill set but once I got through that and I got over that hump and I learned how to do it everything's very simple it's all just stateless functions and immutable data that's it no mess so in summary no runtime exceptions if you want more there's even more at elmlang.org there's a mailing list which is full of friendly people as I discovered so the big question sort of would I like to ship another production web app in Elm? oh yeah thanks very much