 Hi everyone, I'm Shavek Khurana and I'm here to convince everybody that you should start writing closure script to compile your JavaScript applications. I think somebody else did the same, Oman did the same with Svelte, but I have my different reasons. I've been working as a hobby web developer since 2008 and most of my expertise lies in building B2C, enterprise applications. Sorry, the clicker stopped working. Around the year 2012 to 2016, I was working on an LMS that naturally evolved from one application to four UI frontends. There was an admin panel, a web frontend and two native mobile applications. And when you work on projects for long periods of time, your mistakes from the past come in by two. When the business would come to me with some feature requests or some bugs, I would go back to the application and see that the router that I depended on has been depreciated or the state management that I depended on has been replaced by Redux or one other framework. In the span of four years, I changed the build system thrice. And it was just funny to see how the entire community moved from grunt to gulf overnight. Now I am somebody who likes to focus on business problems. I'm not somebody who would like to talk about languages. And I just wanted the ability to have stable applications that can be extended after months time or maybe six months of inactivity, maybe an year of inactivity. And certainly JavaScript didn't cut as a tool. I researched the problem and I was able to put the problems of the JS community in this highly scientific equation. And it basically means that the language itself is imperfect, but the community is very talented and enthusiastic, that leads to high velocity open source development and a ton of abandoned lives in ideas. I think there are 50 versions of state management that are similar to Redux. When I started questioning my toolkit, I found my answer in closure and closure script. So these are two different languages. Closure is a language is a functional list that compiles to JVM and closure script is the same language, but it compiles to JavaScript. And Nolan Bushnell said that most good games should be easy to learn, but hard to master. And we'll see in the next three slides or four slides how easy it is to learn closure script, but you'll have to spend some time to be good at it to master it. Closure is a list, which means that instead of writing imperative code like you do with JavaScript or other C style languages, you write your code in the form of trees. It is functional and immutable, which means once you have defined a data structure, you cannot do anything to change it at runtime. And instead of wrapping your data inside nice states and objects and exposing DSL's on top of it, you just talk to your data directly using languages native APIs. And in cases where you want to mutate the data, like if you have some form state that you want to change, you could use set safe constructs called atoms, which lets you safely update the state of any data structure, strings, maps, anything that you could think of. And closure is homo iconic. I guess this is the most important slide in my presentation. And I just want you to keep this in your mind because I'll refer it over and over again. So instead of C style languages, where the difference between syntax and data is profound closure closure wants you to write your code as if it were data. You can see here that the your function is just a list of vectors. Unlike JavaScript, where you have specific syntax to define a function. Your code is just data with languages like closure and closure script. There have been many talks here about why you should write TypeScript or why you should write reason or swelled. And instead of going more into the language semantics, I'll just give you one reason why you should consider switching to closure script, why it deserves your attention. And for me, it was the repel. It is not like the repel that among showcased, it's a little different, but the you just don't try to mix those ideas. What we currently do as JavaScript developers can be termed as observation driven development. So you have a feature that you need to build to write some code. Your transpiler will transpile it and update your application in the runtime will perform some actions. Maybe you'll fill a form and then you'll observe what is happening. And if if it if it was fine, then you can just go ahead to the next feature. Otherwise you'll go back and fix the feature. The cycle just continues in two different environments, your text editor and your runtime, your browser with closure script and closure. Uh, you have a special element sitting between your runtime and your browser, which we call the repel. And what this lets you do is talk to your runtime without interacting with it. So you don't perform actions. You don't observe the runtime inside the runtime. You just eval code inside your editor and you can talk to the to the runtime. I don't think my words can explain it as well as a demo can built a small application or a tic-tac-to application, which has two pieces of state. There's a metrics that maintains who has marked at what position. And there is a state that manages who's turn it is. And there's a react component that takes the state and renders it and gives you methods to interact with it. Can you see my screen just fine? Okay. Thank you. Uh, on the right, I have the application on the left. I have my code and my runtime and my editor are connected using the repel, which is running in the terminal somewhere. And what I can do is I can evaluate code from within my editor inside the runtime. Just notice how there was one printed on the console. What I can also do is interact with JS elements again from inside my editor. I'm just executing code from within my editor and the repel takes it bundles it and executes it in the runtime environment. By the same virtue, I can read the current state of the runtime inside my editor so I can ask the repel about how my lattice looks like, which is everything is knit. Now this lets you do some pretty nifty things. Uh, I'll go to the UI and I'll click on element zero, zero. Okay. I've clicked on it, but nothing happened. This is a bug in my application. And if you had the bug similar to this in production, what you would do is maybe check the state, maybe check your fancy reducts, Dave tools, maybe check the react Dave tools, or maybe just add plain old console log statements and see what is happening. But since we are in a more sophisticated environment than the regular JS ecosystem, I can just ask my editor, my repel to tell me what's up with the state. You can see that the first element of the first row is X in my state, but my UI has not changed. That tells me that the components are not reactive, which I have done on purpose. So I'll just go back and make the components reactive. I saved the app has updated. And now I believe it should start working so I can just go there and check it. Perfect. It started working now by repel driven development. Since you can talk to your runtime without interacting with it, you can do things like resetting state or just imagine me not having to go there to interact with the environment. I can just execute code from inside my editor in the in the runtime. If I go ahead and start playing more, I'll notice there's another bug in the system. So you can see that one one is marked by O and it is excess turn. But if I click one one again, I'm able to overwrite it. Now another bug in the system and all we need to do is go back to the editor and figure out what's up with the move function. So this is the function that is responsible for making the marks. I can reset the state and see what's up with it. I can move an element to zero zero. You can check that the move function works only when you can move to a specific point. So if there's another function called can move and if can move returns true, it's only then the state will be updated. So you see that zero zero is marked already and I can ask the repel if I can move to zero zero again. And it says true. That is the bug that we were looking for. So I'll just go back to the can move function and fix it. Notice how I'm not going to reload the entire browser. I'll just take the can move function and plug it into the repel inside my runtime. So there was no change in the state. There was no live update in the application. But now if I go back and check can move function, it returns false. I did not leave my editor, but I was able to fix a bug and I can just go back and verify in the browser. Zero zero is marked and it's all stern. I'll click on it again and nothing happens. That means I was able to fix the bug without going anywhere. What this lets you do is just focus on one function or a couple of functions that that is just one functionality. Instead of focusing on the entire application and waiting for it to transpile and reload in your browser and remaking the state, you just take one function inside your editor, work with it, develop it, fix it and move on. But this also lets you do is just tested in a better way. So I have a few instrumentation tests at the bottom. I can reset the state and I can check if marking all marking the first column with o makes o win. Yeah, it makes it win. I can also check if marking all the all the elements of the first row with o makes o win again o win and just notice how I'm not talking to the runtime, how I'm not interacting with the runtime at all. I'm just inside my editor and I'm able to execute code that works in the runtime. And what this lets me do is just focus on one thing. I can also go ahead and turn off the UI and I'm going to execute some code. I've reset the state. The lattice looks nil nil nil and I want all of you to just focus on this piece of code. I'm going to execute it in five seconds and then I'll ask you what has happened. Okay, your time starts now. Okay, five seconds are up. I'll execute this code. Something has happened to the state. I'll show you what the state is like. Notice we don't have the browser open. And something has happened to the state. Can you tell who has one of X who would bet that X has one? Who would bet that O has one? Who would bet that the game is still on? And you don't need to go to the browser to check it because computing the winner is just another function, which will tell me that X has one. And you can if you want to be sure if you're a skeptic, you can open the browser and you will see that indeed X has one. What this repel driven workflow lets you do is just work with one function, test with inline feedback without leaving your editor. And at the end of the day, your development cycle is stored inside the Git workflow. So when you come back to this feature again after six months or after one year, you'd know exactly what your thought was. And you and your team as well would know. And you can just repeat that process seamlessly from within the repel. The editor integration that I was using was Cider combined with Emacs, but you could do this, you could connect any editor to the repel or using the plugins that are available. They are plugins for most major editors. Now, when I first saw the repel demo, my I was convinced that there's no way that this thing is in fraud because the feedback cycle is reduced to a point where you just focus on one function. And I would like to debunk this myth, because this thing is very well-inproved and it has been in broad for over 10 years. So much so that you could enter off with the JS ecosystem natively. The Google the closure script relies on the Google closure compiler. This is different from closure. There's a spelling of s in closure and J in closure. This is a different library that lets you write better JavaScript. It does your tree shaking for you. It applies aggressive optimizations. It occupies and minifies your code. And Google depends on has been depending on it for over 15 years now. This is the same library that closure script uses to spit out JavaScript code for the browser and node environment. Interacting with JS objects is seamless. So if you want to talk to a full object, you could just append JS or slash them space and you could talk to any available JavaScript object. You could also convert from closure data types to JavaScript data types seamlessly. Consuming npm packages is a breeze to just yarn install them and use them as you as you would use any other function. And writing node lips is equally simple. You just define a function and you can tell your build config to by using the export keyword to not aglify the name of that function. Or you could just use the export keyword inside your code. This again will tell the closure compiler to not aglify the name of the function. And you could use it in any node or browser like environment. I hope nobody read that code. And going back to homework on a city, since you're just using data structures to write functions, your react components are like simple and easy to understand the equivalent JavaScript component for this functionality would look like this. And if anybody was wondering that this language is overflowing with brackets, I want you to observe the number of brackets in the JavaScript equivalent is way more than the number of brackets in the closure. Almost always the amount of code that you write with closure will be less than what you do with JavaScript and combining these two superpowers or interop with the JavaScript ecosystem and the repel. Just if developers are able to deliver more. And I guess that's why they are most paid throughout the world. The strength has continued for over three years now. But what about types? Types are important and closure is a dynamically typed language. I don't like TypeScript, but still I understand the importance of types. As your system grows, it's easy to reason for and grow and extend your existing platforms. The answer to types is available as a closure library called spec that is short for specification. And what spec lets you do is define your types, the types that you're operating with in the form of predicates. So unlike reason ML or TypeScript, where the concept of type is first class with spec library, you could just define types as predicates as just functions which return true or false. And it is optional. So you could just work on the peripheries and third party integrations with types. Here I have defined a person, which is a map that has three keys. Two of them are required, first name and last name. And one is optional, the phone number. And all of these parameters are just functions. There are no predicates or there are no, there's no first class types integer. The string is a function integer is a function. And so are these inline functions that compute the less than or greater than value. And specs let you do just more than static type. I have another demo for you. I have a form that has three input values. There's the first name, there's the last name and the phone number. We have a validation function that is provided by the spec library. And if the validation passes, the data is submitted to an API, which is a stub in my demo. So since you have the power of the repel and you have your types defined, your specs defined already, you don't even need to interact with the form to check if validation works. So I've just added some sub data and I know the validation would work. And all this goes to my gith history. I can still go ahead and fill in the forms once or twice just to be sure and submitting it gives you a nice error. This is not as human readable as it should be, but there are libraries that let you convert spec errors into more human readable form. Now, not just that, like with other implementation of types, what spec lets you do is generate function, generate stub data that will match the shape of your desired type. So I have a person and I can generate a random person every time and spec is doing that for me. So I can see the variety of data that I'm allowing in by defining a specific spec. Uh, and since I have the power of repel again, you marry that with the power of generative testing and now you can generate your forms without having to interact with it. When I fill these forms with dummy stub data, my mind shuts off. And what spec lets me do is just focus on the business problem, generate data at runtime at development time and my form gets filled. And again, because on submit is just a function. I can on submit inside my editor. So you can see on the right, the data was submitted to the API. I'll do that again. I'll generate some new data and I'll submit it without interacting with the runtime to the kind of feedback that you get is super fast. You can go one step further. Now testing with one or two dummy data is enough, but will get you through the PR review, but it's not enough to make sure that your specs are fine, that your types are fine. But what you could also do is generate code inside the repel and check if what you want is working. So I generated code to generate random data while I'm developing and I could just figure out if this is the data that I want to allow to go to my database. So I can see that the first name includes integers and maybe I don't want that to happen. I'll just go back to the spec definition and make it motors, make it add another predicate that will filter these integers out. Yeah, numerous benefits to spec. First of all, they're optional. So you don't have to spec your internal components or you get generative testing inside the source, which again is saved inside your gith history. So again, when you come back to this application, it will be easier for you to pick up where you left. And these are just predicates. You don't have to learn any new syntax like you would have to do with TypeScript or any of the language, just functions that return hoolien values. And since closure is homo-iconic, you can just spec data. You can also spec your code because your code is just data, which simply means that you could go crazy with specs. There are two libraries that let you write typed closure using specs and your code would start looking like TypeScript. I'll just show you another demo and I won't even bother opening the browser again. I can just go to orchestra. I define a function which is spec that takes an integer and returns an integer. And I can check if it works on one, which it does, and I can check if it works on a keyword. Nothing happens because a nice error is being returned in my console which says that the spec validation has failed in a specific function. Can you read this? If you're not able to read this, it just says that your function was expecting an integer, but you sent a keyword. And the errors are well placed. You can just figure out the function that caused the error. Now I personally would prefer a language that lets me plug in the entire system just as a library. So what you saw happening here was the entire promise of reason or camel just as a library inside the language. It gives you a sense of the robust and simple semantics of the language that lets you extend it seamlessly. I was surprised to learn that the or the async functionality of closure, which is at par with Golang is just a library. There's no built-in construct in the language. You can just write a library to extend it. And this was closure script that complies to JavaScript closure is even bigger on the server side, where you can do the same things you can develop with the repel. You can enter off a JVM and net CLR. So the possibilities are limitless. When I got started, I was kind of skeptic because I want my code to stay in production. I get anxious when my code does not get reviewed or doesn't go to production. And the code that I was writing in 2012 native J was JavaScript or ES six should no chance of being in production after 10 years. But for the past two years, I guess most of the code that has gone into production has not been taken out unless there was a bug. And if the question, if you ask yourself this question, and your answer is yes, your code will stay in production for 10 years. You don't need to consider closure script. It doesn't make sense. But if the answer is no, I think it's a good time to get started. They're just two build systems. There's no competition amongst the libraries. You have line and fig wheel and their shadow CLJS. I would prefer shadow CLJS because that lets you easily interrupt with the npm ecosystem. You'll have to do some hard work with line and fig wheel. There are multiple react rappers. One of them is reagent. And Luke Wharton says that reagent is what react aims to be one day. It's a big claim. I just want you to decide for yourself. I would buy on it, but I just take it with a little bit of little grain of salt. And if you write if you like vanilla react, or there's something called HX that you could use that lets you use the native JavaScript implementation of react inside closure script. And there are a ton of good people that you should definitely follow. One of them being rich Hickey. If you like this talk, even a little bit, just go back home and search for rich Hickey stock. And if that doesn't change your mind, or you can just tweet me and tell me that I wasted your time. There are multiple books and blogs that you could get started with. Thank you. You can find me on Twitter if you have any questions. And I can also take questions right now. How is this better than writing test cases? It's not better than writing test cases. It's just that while you're developing, you don't have to test using observation driven development. I'm not against test cases. You will have to write your test cases, but the general quality of your code will improve right at the development. Hey, great talk. What about the component libraries and the whole set of ecosystem that often comes with money or the modern alternatives of the front end libraries that has react? Sorry, I was on. Did you say that? What about the existing JS ecosystem? So if you use react, you get a lot of third party applications that you can integrate for authentication for components for a slider for a bunch of things. You can import anything. So because it compiles to JavaScript using closure compiler, I had this slide where imported react home, but you could literally import any library that exports using the common JS or the webpack syntax, and you can use it inside closure script. You can just use anything.