 Hi, good morning and welcome to the first talk of this morning at Workrausure. First, let me introduce myself. I'm Christophe Brown, I've been a long timer in pleasure, I've been working in pleasure since 2008. I discovered pleasure when it was maybe three or six months old and I've worked mostly exclusively with pleasure since then. I'm an independent software developer. Up to two years ago, where I joined forces with Baptiste Dupuch, together we are tense critics. Tense critics is governed by two simple rules. The first rule is that I'm always right. The second rule is that if I'm wrong, it's always Baptiste fault. Here is the story of how I got tricked into writing a closure port. It's Baptiste fault. For a long time, he wanted to write a list implementation and he was also very interested in trying to reach out to mobile development. At the start of the first lockdown in Europe, so spring 2020, Baptiste got enough time to try to evaluate the options and among the options, if first evaluated to get in swift and after some time, he settled on that and further. It was totally not on my radar, not a single blip. I was quite amused by his sensitivity. In the following months, I don't know if it's a pure coincidence or me paying more attention on social media to that and further. But I noticed it here and there and seeing mostly positive reviews, especially about Flutter and I think that the tipping point was when I heard both David Nolan and read a positive tweet by Patrick Logan about Flutter and that. So maybe there was something true or at least valuable in what Baptiste was trying to achieve. I took a bit more with him and at last he convinced me. As of late September of 2020, I agreed to help him write closure dot. But first, maybe you are like me. You have no idea or very faint idea of what is dot and Flutter. They are both Google products. That is kind of a very typical static language. There are a couple of things which are interesting in dot. First, it is able to target either JavaScript, its own VM or native code, be it X64 or all. Another interesting part is that it seems to have a conflicted relationship towards the name either maybe is because it's a story already grew as a language. Last, because initially it targeted JavaScript, its concurrency story is almost the same as JavaScript. You have workers communicating through messages. You don't have shared memory concurrency. Flutter is a cross-platform guile and it allows you to target mobile. It also targets web through Canvas and it now reaches out to desktop even. It's becoming more and more compelling to use Flutter to make desktop applications. As I alluded to earlier, dirt dynamism is a bit conflicted. You don't have dynamic loading but you have really good at reloading in the dot VM. It's technically typed more than Java. But it has a pseudotype named dynamic which changes the way methods are resolved. When you use dynamic, you are close to what you get in Java when you are using reflective calls. There's also a fairly runtime type property which can be overridden. When you override it, you can make it without anything so runtime type can blatantly lie. In the same vein, you can only check whether an object in the instance of a class if the class is a compile time constant so you can't implement instant question mark. Now, the chronology of the events. In the spring of 2020, that is started to work on ClosureDart by itself. And that of September, I joined him. We decided to reboot. Our goal was to write a very minimal compiler in Dart for a subset of Closure. The compiler would evaluate ClosureCode and use the auto-reloading mechanism of the dot VM to patch itself, replacing very simple stuff written in Dart by actual implementation in Closure and so on. So growing the subset of Closure until you get a whole language. It was too ambitious. We had a hard time keeping track of what was the current subset. Plus, subset in Closure is not that easy. So two months later, we changed our mind and decided to run the compiler inside an existing Closure implementation. A more typical bootstrap strategy where you write the compiler in the language itself and you use an existing implementation to compile the compiler and get the actual compiler. In one day, we ported the compiler with add in Dart to Closure. It was a single pass compiler. One month later, we realized that we needed to introduce another phase. So we split the single pass in two and introduced an intermediate representation based on S expressions. This design has served us well because we haven't touched it anymore. We just made some course corrections which are more like tactical changes. The first one was made of this year where we realized that if we were going to wait for the compiler to be able to run on the dot VM, we were going to wait a long time before delivering something valuable to us and the community. So we decided to broaden the capacity of the compiler while in hosted environment. Up to now, our only goal with the compiler while running in Closure on the JVM was to be able to compile itself. Now, we made changes to be able to compile any user application with the compiler hosted on JVM. The second correction that occurred is the realization that as we were going better at emitting Dart code, the more precise the types we were producing, the more types we have to get right. It kind of snowballed and we had to bite the bullet and really produce good type inference across all the leaves, using the Dart and other and so on. And this is what has mainly kept us busy since the end of the summer. Besides the compiler, we have 80% complete Closure implementation. Some things are lacking like sorted collections or multimessors. Otherwise, we have most of core, some auxiliary namespaces. We have good interrupt with Dart. All Closure collections are Dart collections and Dart collections can be passed to Closure functions. We support generics, which is important because in Dart, generics are not erased like in Java. We also support the name parameters. We have a lot of things. But interrupt was really important to us. It's even the first thing that we prototyped because one of the pillar of Closure is its interrupt capacity with the host. Let's cover some specifics about Dart, well about Closure Dart. The first thing is optionals. So in Dart, a method can only have one signature. There are no overrids for a given method. But it can have some optional parameters, either positionals or named. For a long time, we had a special syntax for the named parameters. We used the Dart in person to tell the compiler where the name parameters were starting. We don't need it anymore because we have the static information needed to know how many fixed parameters are expected. You are just going to write what seems the more natural keywords to denote the name of the parameters and that's all. Another point of difference between Closure and Closure Dart is that in Dart, types are not nullable by default. This is something that changed over the course of the project. It was in the pipeline when we started, but we chose to ignore Dart 2.12 introduced non-nullable types by default. It means that when you've got a function in Dart that returns string, it's not going to return a nil. So it means that for Closure function, like namespace, which may return a string or may return nil, you can't type in a string in Closure Dart. You have to type in a string question mark. We doubled with the idea of reversing the behavior and have a string by itself denote string on nil and string exclamation mark denote strictly a string. But after some experimentation, we realized that it was doing to create more confusion and more distance with the host. So we keep the Dart way, which is to put a question mark at the end of the type. Still speaking about nil, in Closure, everything is true except for false and nil, and it's the same in Closure Dart. However, to make tests more efficient, when we know that we are going to get a bool, we don't test for nil. When something is clearly not a boolean, like it's a string question mark, we only test for nil. When, as a user, we know that it's not going to be a boolean, we can use the sum metadata. For example, the sick function is going to be written either nil or a sequence, and a sequence is whatever implements the sequence protocol. So we can't type what a sequence is in Dart, but we know that it's not going to be a boolean. So we have this sum pseudotype, specific to Closure Dart, to be able to take the compiler. It's going to be nil or something which is definitely not a boolean. Now, generics are not erased in Dart. In Java, generics only exist at the level of the Java compiler for the JVM that don't exist, so you can bypass many things. It's not the case in Dart. First change is that we need a way to encode the information about a parameterized type. And we have this constraint that the closure reader expects a typing to be either a symbol or a string. So we could have chosen to encode in a string the parameterized type, but it has drawbacks. Because you have to parse the string and you lose structured editing once you are in a string. After some head-scratching, we came up with the idea of putting the type parameters in metadata on the symbol. By the symbol, I mean the symbol representing the type. So you put meta on the metadata. It's frankly a bit bizarre. But we realized that we could leverage taglids to emit this symbol with metadata. And so we have a taglids role for slash, which allows us to write least pressure on a string to denote an optional list of strings. Another thing about the generics is that they impact collections. Because when in Dart or in Flutter, you have something which expects a list of widgets. You can't pass a person vector as the list of widgets because a person vector cannot hold anything up full. In the Dart collections API, there are cast methods, which are a bit magic because they are parameterized by their return type. But they allow to wrap a collection of a given type into a collection of another type. For example, a list of objects can become a list of strings. It's just a wrapper. The list is still a list of objects underneath. And the type of the actual elements will only be checked and demand when they are retrieved from the list by, for example. So you are moving a static errors to the dynamic realm. It offers us a way to transform a person vector of object, which is a Dart collection, a Dart list, to a list of widgets. But sadly, once you go this way, the object that you have is the list wrapper from Dart. It's not a person vector anymore. So it goes against an important design constraint of a closure, which is to avoid wrappers at all costs. Then we realize that we could have type parameters on closure collections. These type parameters would be totally ignored. They are there only to placate the Dart type system. And so when you need to cast a person vector to be a person vector of widget, we are just creating a new root which has the correct type. But it's still a person vector implementing all the closure protocols being still equal to the previous one. And currently we are working on getting the compiler to insert the code cast itself so that you don't even have to care about your vector not being of the right type. There will be a dynamic vote to be able to be one when this magic behavior occurs. By default it will be on. When we are on dynamic forms, in closure you've got one on reflection. In closure Dart, the equivalent thing, which is one on dynamic, is on by default. Because it's more important, in our opinion, in Dart, to get the correct types. So when closure Dart struggles to determine the type of an expression for an interrupt, it's going to complain. Another thing about Dart is how do we require Dart lib from namespace. Here, which shows to do it in the same way that closure script does. If the namespace is denoted by a string, then it's going to be a Dart lib. Another thing which is important in Dart because it's leveraged by a lot of API is that Dart has built-in support for a sink and a wait. So the first reaction was, OK, we've got clear sink. But clear sink is a word on its own. Clear sink has no good interrupt story. And here we have something built in the language and the standard library. So we need to refer something low-level to be able to leverage that asynchronous feature. It's pretty simple. We introduce a new special form, a wait. So to summarize, we learn Dart so you don't have to. So that you can reach out to mobile, to desktop, to native applications without having to learn the language. Only learn the libraries and in particular to learn Flutter. Now, Baptiste is going to give you a short demo of what it is to code with closure Dart. Hello, friends. I am Baptiste, the other half of Tense Critics and the Closure.Compiler. I have four minutes to show you what it's like to use Closure.Dart for writing iOS and Android applications. So basically, I have a Skatefold application with only text. If I edit text here, this text is not centered. I have to recompile Closure.File, reload the application and yeah, we see the text. So now what I want to do is just build a list of dates in French. So to do that, we need to use a Lisieux component, which is a default component from Flutter. Lisieux takes a children property, which is a list of widgets. So the list view, it takes children and has input, we have a person vector of strings of dates. So I want to build some Flutter widgets. I'm going to use this tile widget, which is just a tile, basically. And it takes a title, which is also a widget. So material, list, tile, and it takes a title, which is a widget. So I have to use widgets, text, and I can give him the input one. So now let's try to compile it, list, view, compile dates, reload the application. Oh, it doesn't work. And it doesn't work because children wait for a list of widgets and we gave him a person vector of dynamic. So person vector implement list. So this part is good, but dynamic is not widget. So on this version of the compiler, we have to cast inputs. It will be done automatically, magically, when the compiler is open sourced. So just cast this vector of widgets. Now we have a list of days in French. We can even add some other components. Let's say we want a divider, material divider. And here we go. So basically we use, we are using closure data structure to build our widgets. We have a lot more experience now with bigger applications and it's been a blast. We are very excited to open source closure that soon. We still have some work to do on a typing mission and magic casting like you can see. And I hope you enjoyed this video. Thanks a lot. Bye. So I guess that by now your main question is, when can we get our own on closure data? There are some things that we want to fix. First finish the work on typing inference. There are still some things to tune. And there's the introduction of the magic cast. And last there's something about interrupt which is pretty important. It's about how doubt functions and closure functions relate. With more experience, with doubt now, and a better understanding of the language. We are questioning some design choices that we made earlier. So our current estimate is to release closure doubt in the first quarter 2022. Finger crossed. Last thing. This work wouldn't have been possible or not at this pace. Without the support, the faithful support of our sponsors. I say faithful because these are people sponsoring us, believing in us. Even if currently all you get is vapour oil. There are dozens of individuals who helped us and two companies, New Bank and Romo Research. Both supported and still support our work. So thanks to you all for listening and thanks to our sponsors again for helping us bring a new closure implementation. That will increase the reach of closure. Thanks.