Record & Tuple: Immutable Data Structures in JS


Record & Tuple is a proposed feature for JavaScript that aims to introduce new immutable value types. Records are immutable key/value structures and Tuples are immutable sequences of data. In this talk, Robin, one of the champions of the proposal will introduce the feature, show how it can be used and explain how this feature is advancing in the TC39 standardization process.


Oh, that's a lot of people. Thank you for coming. I'm Robin today. We're going to talk about record in Tuple and this is about new feature in JavaScript that hopefully you'll be able to use I guess soon and it's Hopefully going to redefine the way you handle data in JavaScript. So again, I'm Robin. I work at Bloomberg. I do JavaScript infrastructure. And so I work with thousands of developers in my company to improve their JavaScript experience. I'm also tc39 Delegate for Bloomberg. That means that I get to participate in the standardization process of the JavaScript language. And also I'm one of the author and code champions of record and Tuple. That's a good thing because today we're going to talk about them. Okay. What are we going to cover today? First? We're not going to talk about record and Tuple but the objects and the types, you know and love in JavaScript today. Then we're going to look at record and Tuple and finally, we're good. I'm going to tell you when and if you can use them. Okay. So let's start with objects you already use them and we're going to talk about other types such as strings numbers very basic stuff, but nevertheless it's important to take some time to look at them. We're also going to talk about how they are being referenced and how they're mutable in some ways. Let's start with Primitives. And in this case we have strings on the first line. We create a string on the second and we create a second string or do we create a new one or is it the same string? That's the question for JavaScript when you put a primitive value in a variable and you basically use that variable somewhere else and compare it if the value inside matches exactly the same characters in the case of a string it's going to tell you this is the same value the same thing goes for numbers. For objects. Well on the first line here, I'm creating an object on the second line. I'm creating a second object whether they have the same internal stuff in them is irrelevant here at every line. I create a new reference to a new object. And essentially we're going to point to another place in the memory. So we have two references to two different places for JavaScript. Those two references are not the same thing. They're completely unequal and they're not going to match. So I I don't know if you tried to change one character in string, but if you try to do it at least in strict mode, this is not going to work out you're going to have an exception and you're not going to be able to mutate the internals of the string, but I'm pretty sure you're already done that with objects and changed the internals of an object by just setting something into specific key. So here I'm just changing the name key and everything goes well. But some of you might know that you can freeze objects that makes them basically immutable. So why would we need record into both? We'll get to that later. But yeah, I can freeze my object and now I can change keys. So that's it. It's done mission accomplished except That it's non-recursive. So if I want to actually mutate the array inside of that object. I can actually that's a good thing here because I wanted to my colleague Ashley to the champion group because it's been participating a lot on making record into for amazing. Okay, so Before we go further some of you might know that mutating things. Sometimes is a sleepery slope. And so if you know that this is a problem. This next part is going to be yeah. But it's still an interesting example here that I want to show you. So here let's say I get this init connections function from a library. I don't really trust it, but I need to use it. So I don't trust it to not change my config argument and passing it down and I don't know if that happened to you but that happened to me once at least or twice or three times many times actually the config here. I don't want it to be changed because I'm going to use it on other places in my application, right? But in it connections could very well change it. So what I'm going to do is freeze it then I'm going to pass it to any connections and then I'm still not sure that my database key is not going to get changed. So here's an idea. I could Jason stringify it and then Json parse it and then I get a copy and everything's fine, right? It's going to be pretty slow to do this. And if I'm going to start doing this in a hot path, it's going to be a pretty bad idea for my performance. And if you were to do this, please use structure clothing instead. It's available in most hostile environment. So your web browser node, do you know has structural and please use instead of stringify bars? Okay back to references. We had a mutably problem, but I want to talk about references just for a bit. They can be problematic sometimes so here is an example that hang on with me and many lines. But the first line creates a boat with a really nice name the second line creates coordinates for that really nice name Boot and then I'm going to track all of the boats in the sea by using the boats map. It's an es map available since es6 and I can use my coordinate to map to the boat right simple. And if I want to look up the boat, I just give the coordinate to the map and I'm going to get back the boat. Except here's what I'm going to do next. I'm going to copy my coordinates for some reason. Don't ask me why. But if I'm trying to use my copied coordinates to look up the boats, I'm not going to get my boot because I get another reference which is the reference to the copied coordinates. And how can we fix that? Let's stringify it. It's easy. I get a string. It's a value. It's going to match up in my map amazing. But this is a slippery slope. If I were to create microordinates just the other way around and not inserting the keys in the right order. I would get this. And an equivalent string. So this is kind of fragile approach. We really don't want to be doing this. And on top of this you cannot put object Cycles in there because Json string if I won't like it and you cannot also put unseriosable objects and values in there. So let's do a quick recap Big for we see a potential solution to this. So Primitives, there are really cool the variables hold values on to them not references so you can compare them easily and you cannot mutate them when it comes to object. They are held by reference, which is good. It's very important in the language that they behave like this but in our specific case, it doesn't mean like the best thing right and you can freeze them, but it's not super comprehensive. So what if we had a way to wish them values together and still treat it as a primitive type? And so that's where I conveniently introduced to you record in Tuple. Yeah. Here's your first record. It's very much like an object. But as you can see there is this little hash symbol in front of it that makes it a record. And I'm not going to spell it for you. But this is a tuple same thing. You have this little eye symbol that makes it from an array to a tuple. So just one character difference. It's going to make a pretty big change. Obviously you can combine them for trackers inside of tuples who was inside of Records. They're immutable by default. You create them. You put this hash character. You don't need to freeze it. It's just none modifiable after it's been created. That's it. And that also goes deeply into the structure. So no problem with freezing recursively. We don't have to think about this. and I think quality semantics of those things are great. Because instead of comparing references here if I have two tuples that have the same sequence of values in them. There will be equal. If I have two records. I have the same pair of keys and values they are going to also be equal and we're going to use that. And that's because they are Primitives. So if I type of them I will actually get their own type of they're not going to return object. They're going to return record and Tuple. Okay. So let's solve our previous problems that we had with the objects, right? So about the freezing what we don't need to so sorry, we don't need to freeze anymore because it's completely immutable if you need connections try to change my config. It's just going to crash so problem solved I guess. When it comes to the second problem. Well, we talked about equality with triple equal but map will also follow the same kind of equality. That means that if microordinates from an object becomes a record now, it's basically instead of compare references to the coordinates. It's going to compare the internal values of the coordinates. So if I create a copy of exactly the same coordinates since the values inside of the coordinates record are going to be the same. We're going to still be able to look up our boat, finally. Okay, what about object cycles and answers of all objects and values. I talked about that earlier while you won't be able to make them with record and two post structures. We're going to get to that a bit later and what about the key ordering fragility with the stringify that I showed you earlier, right? If I insert my keys in a different order. Would that change anything? With records no because records don't memorize the insertion order. They just lexically return to keys in the order that are released ordered. So if I take the two coordinates if I insert my keys in different way, it doesn't matter still the same values inside still the same equality. Okay. There is no freelance here. You cannot do some things with record and tuples and for good reasons and we're going to go through them. First of all, you cannot put an object in there. If you look in this slide, I forgot to put a hash in front of my DB object here. It's an object now. It's not a record and Records don't like to have objects in them. Unfortunately that also goes for functions because functions happens to be objects. There is still a way to fix that problem and I'm not going to talk about it because it's solution that you will be able to use it. But I only have 20 minutes. I actually have 9 and 9 minutes left. So I need to speed up. Okay, so now we're going to talk about how you can't derive changes. Obviously you can change things in place, right? You cannot push values in place to a tuple. How do you do this? Well, we've erased you can. Concat things using the spread right? You can do that with two poles as well. And as a matter of fact, you can do that with records as well. So if I just want to change one value in my proposal and create The future I'm going to update it by spreading the proposal and changing the stage key here. We're not there yet, but soon. Okay. Beyond that there are some really useful methods on the array prototype, right for example reverse. Unfortunately, it can't exist on Tuple because reverse changes arrays in place. We are introducing two riversed two reversed is going to not change the tupole in place. It's just going to return your new tool that is effectively reversed. We have to reverse that is doing what reverse is doing. We also have to sorted that is doing what sort those but not in place we also have with is equivalent to doing an index assignment except it's not doing it in place. And finally we have two splice that does whatever splice those like don't ask me any Returns on YouTube all Those could be very useful in standard bug down arrays, right? That's a good question. We added them in another proposal change your way by copy. It's a cool proposal again a huge thanks to my colleague Ashley for pushing that to stage 3, but that means that I can write this beautiful function sort by name. This function will work on arrays of Records or arrays or objects are two pools. Of records and this is going to sort my names that way so my colleague Rick and Ashley. Were probably started and then Rick Astley in some absolutely. Sorry about this. You're lucky I couldn't get the song Because for IP reasons, they don't want you to play things, but I'm sure you have it in your head now, and that's that's efficient for me. Okay, let's summarize now. The syntax pretty easy you add the hash. It's immutable. So if you want to create derived updates you need to do it by copy for either spread or the new methods that I showed you. And we also backboarded the methods to arrays which means that you can write functions that will work for both. normal objects normal arrays and records and tuples we also have value equality instead of referential equality and we have this working across all kinds of equality in the language which is triple equal so strictly quality map and set They cannot object they cannot contain objects or functions, unfortunately, but stay tuned here. This is probably another complete other talk, but it's very interesting Rabbit Hole. So stay tuned. now you might be asking yourself the question. When can I use that? So record in Tuple is a stage 2 proposal at tc39? What is DC 39 DC 39 is the standardization venue for JavaScript language actually should call it xmascript language. JavaScript is an oracle trademark. And then comes stage 2. There are four stages in tc39. So stage 2 is like a bit in the middle. But essentially that means that the committee expects the feature to land in the language. So even if it might and it will probably change what I just showed you today, it will ultimately still end up in a language. More info on this whole process with humans talk. I think it's on Monday on the online tracks. You can know much more about how tc39 work there. I would hardly recommend following this one. Okay. So what have we done to progress in the next stage? The Proposal is being reviewed by multiple people and so people in my company, but also it outside in other companies as well. And my clicker. Yeah, and we also have a babble transform and a polyfill for it. Also, we have specs that are being written and we also that's spoilers No. Okay. We also have a Firefox implementation. That is bi the compass like you cannot use it yet. Unless you compile Firefox yourself, which you should try. It's really fun. And then when can you use a feature? for experimentation, you can try it now go on this address take pictures go on and you go and you can try this in your web browser just right there and then for your own projects Let's wait a little bit still stage 2 proposal. Let's not start using it in production anywhere right? It's really not a good idea. What about the new array methods? I should showed you. We can use them pretty much now because you have shims you have polyfills and it's in safaritec preview 146 which means that at the next major version of Safaree that should be around for. Should be there and we also I didn't put in on the slide, but there is also a Firefox implementation behind a compile flag as well. And for existing prediction projects just wait a little bit. I would wait for broad browser support for those features. Okay. I wanted to thank my colleagues from the record into full Champion group before I leave you Rick. Rick has been my main character from the beginning day one actually and he made the playground that you will be able to try Dan has been mentoring us. So it's been reviewing our early stuff helping us with going through the process of tc39. And then nicolu Bible maintainer now working at egalia. He has been reviewing the spec because obviously implementing spec in Babel, you know how to read spec afterwards and he also did the first implementation in Firefox and really impressive work. And then actually that join us. I mean I would have said recently, but he's been a while now and he's been doing a lot of spec work the Fixing a lot of things finding edge cases. So huge thanks to him. And finally, I wanted to thank you. All here are Js. Nation also online. and here and Amsterdam I'm Robin, I work at Bloomberg. You can find me on Twitter. You can find me on GitHub. And if you want to know more about what we're doing with JavaScript at Bloomberg come talk to me as well. And you can also go to that website and that's it for me. Thank you. Thank you. Thank you Robin and we have quite a few questions on Slidell. Let's okay. It's good here. Yeah, okay. We have them on the screen and let's start from the top one. Is there a ways for us to cast objects or arrays into records and tables? Yes, you can use the record and array Constructors to just pass standard objects and standard erase into it just a note here. If for example you're passing an array that contains objects. It's not going to recursively convert your objects to records. So you would still need to do that. Manually. We expect user and libraries here to step up and provide Solutions, but that being said, yeah, it's possible. It's just going to be a shallow transformation. Yeah, awesome. And the question from me personally. How do you agree in your team to call it tuples or tuples American English versus I say I say tuples but topples is absolutely correct. There has been a war and we just like Chose to agree to disagree and that's it. Cool. This is how open source works. Let's take the next one thus record. Oh. Oops, could you please return the questions back to our screen dear AV team? Yeah. Oh, thanks that's record Keys only accept stream. Does it accept other immutable types symbols? No not symbols. We only accept the strings. There are reasons for this we can talk about it aside. But essentially it's we want only strings right now. Fair enough and this question actually it came first what other language libraries have been Inspirations for records and two a lot of them. We kind of took a mismatch of everything I used to. Develop enclosure scripts a while ago got some inspiration there also immutable Jazz. Obviously, we actually talked to Lee that created immutable JS and we got this feedback on this proposal. So I mean, it's not exactly the same thing because for example in the table jazz or even like another functional programming language will let you reference and unmuteable things inside of the mutable data structure we chose not to because it makes sense from the way to JavaScript language work every time you create a feature there is yes a certain degree of inspiration you're going to take from something else, but at some point you also and especially with a very Legacy language like JavaScript that has a lot of baggage behind where you still need to maintain compatibility forever for old code because you can't break the web right so you still need to keep in mind. How the language is working and and kind of integrate nicely like as I've been showing like our goal also was not to create a completely new word with record and Tuple that is completely different from objects and arrays and all of that stuff. But also create this interoperability layer, right? So essentially yeah, I'm happy to discuss this also in the next one. Yes. Yes, and let's take more questions in in-person mode. You'll find the Robin in the special place where you can chat with him and thank you very much. Application. Thank you.
24 min
16 Jun, 2022

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic