AI Generated Video Summary
The Talk discusses various proposals for the next version of ECMAScript (ES Next) and the TC39 process. It covers features such as binding syntax, shorthand property assignments, pattern matching, async match, operator overloading, and more. These proposals aim to simplify code, make it more readable, and introduce new functionalities. The Talk also addresses questions about the committee's decision-making process and the experience of being part of the TC39 committee.
1. Introduction to ES Next and TC39 Process
Hello, JS Nation. We are talking about ES Next in this talk. ECMA has many technical committees that decide and define the specifications of different entities. The TC39 works on ECMAScript and has 5 stages in the process. The first stage is a strawperson, followed by proposal, draft, candidate, and finished. We will be going through interesting proposals in each stage. Some features may not make it to the final state.
Hello, JS Nation. We are talking about ES Next in this talk. I am Hemant. I am a member of technical staff at PayPal, a GDE in web and payment domain and of course a TC39 delegate and you can tweet to me at gnumonth. ECMA, the European Computer Manufacturing Association International, has many technical committees that decide and define the specifications of different entities.
And one such, the 39th, is the TC39 which works on ECMAScript. How does the process basically work like? So we have basically 5 stages starting from stage 0 to stage 4. The first stage is called a strawperson. At this stage, you allow input into the specification. It's more like you have an idea and it's not yet presented in the committee. And stage 1 is more like a proposal. So you have an idea and you make a case for the additional and then describe the shape and also the solution. And what you are trying to solve and what is the solution like and what is the problem that you want to solve for is what you discuss here at stage 1. And at stage 2, you have a draft where you precisely describe the syntax and semantics using formal specification language. And then at stage 3, you have a candidate which indicates kind of, hey, this can be tested with a flag may be on your browser or a node environment. So it's kind of you are seeking feedback on the candidate from developers and saying, hey, use it with caution because now it's under a flag. Just use it and let us know how it looks like. And finally, at stage 4, it's finished and it's ready to be shipped. And sometimes it's already shipped with the flag, as I said, in stage 3, the flag is kind of removed at this stage and it's available in most of the modern browsers and other environments. That's the whole process of how TC39 works, like starting from straw person to the finished after the proposal drafted candidate, of course. Interestingly, this was called as Strawman before, and it's renamed to be Strawperson, which makes a lot of sense.
2. Binding Syntax and Simplification
And the get player here, with the val, gives you an object. So you want to map or as of today, you do a map.call on that value and fetch all the characters. And then you do a take while and say, hey, if the strength is greater than a hundred, give me all of those. And finally, you would probably have to forEach and do some processing. In this case, we are just console logging the value. Can this be better? So on state zero, we have this binding syntax, which makes life easier with the bind operator. If you can think of it as two successive columns here, what we see after get player, you have map and then you have take while and then you have forEach. Isn't it simpler compared to how we are doing it today, probably and how precise and simple it looks like here at state zero we have this bind syntax. So this bind syntax, if you were to summarize in the different variants that it provides, if you see object with the bind operator and function, which is equal to function.bind object followed by the bind operator object.function, which is indeed equivalent to object.function.bind with object. If you have object bind with function value, that's equivalent of function.call object.value. And if you just have bind object.function.value, which is equal to object.function.call object.value. This makes lives much simpler and intuitive to read, understand. And also the syntax looks beautiful, doesn't it?
And the get player here, with the val, gives you an object. So you want to map or as of today, you do a map.call on that value and fetch all the characters. And then you do a take while and say, hey, if the strength is greater than a hundred, give me all of those. And finally, you would probably have to forEach and do some processing. In this case, we are just console logging the value. Can this be better?
So on state zero, we have this binding syntax, which makes life easier with the bind operator. If you can think of it as two successive columns here, what we see after get player, you have map and then you have take while and then you have forEach. Isn't it simpler compared to how we are doing it today, probably and how precise and simple it looks like here at state zero we have this bind syntax. So this bind syntax, if you were to summarize in the different variants that it provides, if you see object with the bind operator and function, which is equal to function.bind object followed by the bind operator object.function, which is indeed equivalent to object.function.bind with object. If you have object bind with function value, that's equivalent of function.call object.value. And if you just have bind object.function.value, which is equal to object.function.call object.value. This makes lives much simpler and intuitive to read, understand. And also the syntax looks beautiful, doesn't it?
3. Shorthand Property Assignments
You can simplify the process of returning specific attributes or renaming them in an object. For example, instead of saying perf is op.perf, you can simply say op.perf. This shorthand property assignment makes life easier.
You would have probably done this multiple times, if you have an object and you have an object with a lot of attributes in it and you're returning particular attributes or you're trying to have a different name for the attributes. So in this case, say you have a performance as one of the attribute perf on ops. So you would probably say perf is perf.ops or if you have object of x, you would say x is object of x and with the bracket notation or if you're de-structuring, you would probably do it like this. So wouldn't it be easier if we have an easier way to do it rather than saying perf is op.perf? I would just say op.perf which should mean that perf is op.perf. And say you have coordinates as O of x with bracket notation. As we saw in the previous slide, it should mean that x is O of x, right? Same thing with destructuring. You could just say a of x that is as good as saying x colon a of x and object notation of x as a of x. So this is a shorthand property assignments on State 0, which makes life easier.
Shorthand property assignments on State 0 make life easier. Another example is the make adder function, which takes an argument x and returns a function that accepts an argument y and returns x plus y. Partial application is a proposal in stage 1, where you can partially pass parameters to a function. This allows for flexibility in applying arguments from the left or right, even on object methods or super properties. It is a powerful feature for functional programming and worth exploring.
So this is a shorthand property assignments on State 0, which makes life easier. Let's see another example where we have make adder, a generic function which takes an argument x and which returns a function which again accepts an argument y. And finally, it returns x plus y. So you could do a make adder of 1 and get add 1 and then you could say add 1 and passing 2 to it you would get 3. Passing 3 to it you would get 4. So basically it's a make adder of 1 which adds 1 to whatever input it's been presented with. Similarly, we have add 10 and this is called a partial application because we are partially passing the parameters that is required for this function. And interestingly, on stage 1, we have partial application as a proposal where if you have a function say sum which takes x and y and returns x plus y, you could say add 3 comma question mark, we are partially applying from left and saying, hey, I would produce this parameter later on and pass it on to add one whenever I need and this should be probably called as add 3 here because we are passing in 3 and we pass in 3 to it and it adds 3 to it and you get a 6. And you could also do an application on the right saying add 5 and you add 5 to it it becomes 7. Similarly, you can do a partial application from left, right for any argument in the function argument so you can have multiple question marks and you could pass in those arguments whenever you need them to and you could also do an invocation with o.f or you could just have a function, it could be a method on the object. So it could also be a partial application that is allowed on the super property. So you get the magic here. So you could do a left right or any kind of partial application, which would definitely help if you're from the functional paradigm where you're solving your challenges in a functional way, which is definitely an interesting proposal to look for.
6. Async Match and Do Expression
It's another extension, the enhancement that recently got added into proposal on stage one is having an Async match. You can have an Async match with an await matchable and, and do the same thing, how we will do it with, on a non-Async way of matching, you could say when A you can await and when B you could do B.then. So basically it produces a promise and you could do an Async match with pattern matching as well.
The other interesting feature of what we have on stage one is do expression. So the do expression basically helps you to, you know, have a block within do, where the last statement is written by default. Say you have in this example X, where, where you say temp is a function call and you say temp is temp into Templus1, that's what the default value is written. But how is it really useful? Say, if you have multiple branching in your code and how would you do it today? Suppose you have constant let or a combination of that in your code, or you want to wrap it within a function to, you know, to maintain the scope and things like that. Here's an example of multiple branching. You could do it as easily as saying, Hey, here's my do expression and I have my if condition. If foo is matching, then I would invoke the function f and that's written value will be assigned to X here else. If it's bar, then you would, you would go ahead and invoke G and that the value of the invocation of G would be assigned to X here again or else you would call it. So you could, you could see how intuitive it looks like compared to probably you'd have done this with the ternary operator and have nested conditions within which kind of makes it, makes your code a bit ugly and probably even debugging tougher times.
Here's another easier, you know, syntax for jsx. This probably most of our friends who are into react would have faced, say if you want to conditionally render components. You would probably put a ternary operator on it, or probably use another component which conditionally evaluates the logic required and renders the required component, right? So it kind of gets messier. Here's a view. Here's how beautifully it looks with do expression. You say you have a nav, you have the home component and you say do if logged in, show the logged out button, else show the login button component. So it's so easy to express that here with the do expression.
7. Operator Overloading and Decimals
Decimals can be overloaded with operators like plus and multiplication, allowing for more expressive syntax and behavior. This feature is particularly useful for defining methods in specific domains. For example, you can use the plus operator with decimals to perform addition, or overwrite operators for CSS numerical values to customize their behavior. Overloading operators can simplify code and make it more intuitive.
And here's an example with decimals, which says with operator decimals, we debated trying to overload the meaning of plus, equals, and other operators and try to get a meaningful expressive syntax and behavior with operator overloading, and the whole intent here is to have such libraries where if the operator is overloaded, it helps you to make better and easier expressions, which kind of helps you to basically define methods that is particularly useful for your domain. In this example, we have decimals which are overloaded with plus. So if you said decimal one plus decimal two, you get a decimal three. And similarly here's another example from the spec where it says with operators from CSS numerical values, you could do a query selector on style and pad left with CSS M three or CSS PX two, and this is how probably you would go out and overwrite those operators. You would say you'd use the operator function here and say, Hey, my plus is defined in this way and my multiplication is defining this way, my equality is this, and my left and right, how do you evaluate? So you get, you get the idea on how you could overwrite the operators and, and finally you would, you'd extend the decimal operator for the class decimal. And then the new, big would probably would get the definitions of the overrided overloaded operators basically for what's been defined here for the decimal operators and stage one.
8. String dot dident proposal
The string dot dident proposal aims to simplify indentation within template literals. It provides a static method on the string object that supports expressions and maintains indentation and spaces in the output. This feature is beneficial for generating code, formatting console output, and writing SQL queries. It is a proposal in stage one and addresses the challenges of maintaining indentation and whitespace in generated code.
We have string dot dident luckily I'm one of the co champions for this proposal if you have used our template returns to generate code, basically you would have faced this problem on how difficult it is to indent within a template literal. So the indentation is maintained. And once your code is generated, so the same indentation is maintained across. She is, here's how the string dot didn't look like you, you'd have the didn't static method on string. We've said string.didn't which also supports expression. So you have an expression here which gets evaluated and that would be replaced in the output with expression. And if the, if you have spaces, the spaces will be maintained. It will not just like get trimmed off. So you have this supports expression as we expect and expression with the white spaces will not be removed. Right? So this, this makes life easier when you are trying to Jen, if you're trying to write code, which generates code, or you're trying to spit out something on the console, which is formatted in the right way, and, or if you're writing an SQL statement or SQL query, which you want to execute as well as short in the output. And there are many such use cases, but string.didnt on stage one is a proposal that makes things easier in this realm.
9. Pipeline Operator and Object.hasOn
The pipeline operator is an unsettled syntax with four variants. It allows for nested calls and simplifies code. The object.hasOn proposal in stage two provides a shortened method for checking if a property exists. Instead of using a long chain of functions, you can simply use object.hasOn(property).
The other interesting proposal, what we have is the, the pipeline operator currently, it's an unsettled syntax that are like four variants on how pipeline operator can work. And here's an example. I've picked up one of such syntax say you have two methods, double and increment, which obviously does doubling and increments by one or N, whatever you pass, pass it, take an N and add one to it. We thought pipeline operator, you would probably, would have to have this nested calls. You would say double increment, double and double that's the use case. So if I give you file, you should get 42 out of it. So with pipeline operator, the basically what it does, it needs an expression and then it's has the pipeline operator there and it has a function. So if you were to say five, double and double, and then increment and double, you would get 42 and that's how beautiful the syntax looks like. So this is on stage one, the pipeline operator and object on, has on is on, has on is on stage two, this was one of the interesting proposal that directly landed to stage two when presented to the committee and all it does is it gives you this beautiful shortened method if I could call it to saying that object on has on which takes the object and takes the property and says whether that property is there or not. As of today, we'll probably have to do object or prototype.hasOn property and call the object with that property and then check if it's there or not. So instead of going through that kind of a long chain function, you can just say object.hasOn passing the object with the property and says whether the properties are hasOn as does that property has this property has its as its own property or not. So that's object.hasOn on Stage 2.
10. Map.prototype.emplace Method
And we have map.prototype.emplace. This is a very useful method for working with maps. It allows you to check if a key is present, set it if not, and easily perform operations on it. The emplace method takes care of updating or inserting values, making it convenient to work with maps.
And we have map.prototype.emplace. This, this, this is a very useful method if you're, if you're working on maps today, say if you were to check if a key is present in a map or not, and then set it and then get the value, you would, you would probably do map.has, if map doesn't have that key, then go ahead and set it and later on, you can get and do things on it with emplace. It gets very, very cheeky and easy. You could just say map.emplace key and then insert the value on do thing. So map.emplace basically takes a key and needs to update an insert values. So you need not crack your head on checking whether your map has you already, if it is there, then updated. If it's not there, then create it. So all of this is taken care of by emplace. So map.product or emplace on stage two.
11. Records, Tuples, and Find Last
On stage two, we have record and tuples. Records are deeply immutable object-like structures, while tuples are deeply immutable array-like structures. Records and tuples provide strong immutability and are useful for functional programming. Another proposal on stage two is find last and find last index, which simplify finding the last element or index in an array based on a condition.
And on stage two, we also have record and tuples. So you could think of a records as deeply immutable object like structures. Here's an example of a proposal, which has ID, title, content and keywords. And then you go ahead and say a proposal or title, it prints records and tuple. And then you go on and spread it like objects and say title is stage two record in tuples. But if you go on, say proposal to title, it says stage two, a record in tuple. But your proposal would still have the same record and tuple. So it's more like an immutable object, like structure. That's that's record for you. And tuples are mostly deeply immutable array like structures are similar to records. You can say hash followed by one, two, three, that would be a tuple. And then you could say with zero comma two to kind of get those parts of the tuple. In this case, you say, hey, go ahead and replace the zeroth index with two. So basically you get tuple two to be equal to two, two, three. Whereas tuple one is one, two, three, and these two aren't equal. So you could also do a spread of those. You could, you could say pushed with four. You could use the popped method. So, so all of these methods are available on tuple, which basically helps you to have an array like a structure, but it's a DPI immutable. So if you're into immutability and a functional programming, probably would be using immutable JS and likes and recursive tuples gives you that strong ability of having immutable structures in your program and find last, and find last index is another proposal on stage to say you have an array of values. And today, if you were to try to find, the index, the last index, or the find of the last element in the array, you would, you would probably try to take the array, reverse it out and do a find index, right? Here's an example where it should have been minus one, but it is four. You're taking an array, reversing it, you're doing a find index and saying values equal to equal to 42. It should have be minus one, but it will be four today. If you see your array has values of one, two, three, and four with find last method on array, you could just say, array dot find last. And give it a condition here. We are saying if it is divisible by two, then it give me the last one that's divisible by two. You would get that value. And you could also do a find last index. If it's, if you're working on the index you could get the same idea here, where you say end dot value is 41. Give me the index here.
12. Throw Expression for Error Handling
You can use the throw expression to throw a new type error inline and specify the exact cause of the error. This is useful for checking the availability of parameters and handling errors in a more precise and expressive way.
It gives you minus two because there is no 42 here. All of the values are one, two, three, four and divisible by two. Give me the last index that's divisible by two. You get 0, 1, 2, and you get that as the result on the find last and find last index. And basically you have the throw expression on stage two, which is also an interesting proposal. Say, if you're if your function is receiving a parameter and it expects it to be there, you could throw a new type error inline rather than asserting it inside the function to check whether the parameter is available or not, you could also do it within the arrow function bodies, or you could do it with conditional expressions and, and basically also in logical operators. So you could throw this new error wherever it's required inline. Which is useful. And if you're from programming languages like Perl, where you could say all die, a similar thing, or you could do it as an expression. You can throw the, you know, throw an expression wherever you want.
13. Built-in Indexables, Error Cause, Top-level Await
On stage three, we have built-in indexables, error cause, and top-level await proposals. Built-in indexables allow fetching elements by index, including negative indices for the last elements. Error cause proposal adds an option to the error constructor to specify the cause of the error. Top-level await proposal allows using await at the top level within modules. These proposals are in stage three and show great potential. Thank you, Hemant, for the talk.
And on stage three, we have art on built-in indexables. I'll say you have numbers of as, as arrays, or you have name as string or have your unit eight array. You could use the app or method to fetch or whatever element you want at that particular index. So if you say nums at zero, you could get to zero and nums of minus one, you would get three. That's like, going from the last index, those minus the negative indices suggest that, okay, go and pick the last element from that. So if you do minus one, you get three, you do minus two, you get two. And if you see a hundred or something, you just get undefined, which is not there in that range. And you could do the same things for strings and unit data.
And error cause is another proposal where I'm co-championing. This is an interesting proposal, which kind of adds an option back to the error constructor. If you were to throw a new error, you could pass in the cause and say, hey, this error was caused by this particular failure or other thing. Right? So you can say you have a function and then you're throwing a new error. As of today, you would say, hey, this failed because of this error, but what is the exact cause? And how could you see that in these track trace? Right? So that's where error causing plays a key role. So you have an async function, you're trying to fetch some data, you catch the error and you console log the error and then you console log the error caused by E.cause. And that cause is the cause that was thrown here in the fetch data. So the output you see is error unable to fetch data, https example.com caused by type error, failed to fetch. So that's the cause, that's the error that gets passed in the cause attributes in the option that's passed to the error constructor. So that's an error cause on stage three.
And on stage three, we have a top-level await. If you were to say, do await.promise resolve or any promise main function. As of today, I would say, await is not a valid function because it needs to be wrapped in an async function. But within modules, you have top-level await, where you can have await at the top level. So if you were following this for some time now, you would have seen that there was an article written about how top-level awaits are a foot gun, but then the same author saw the proposal of how top-level await is useful. And then said, yeah, it makes sense within modules. And today we have it on stage three and soon to be on stage four. And that's all we have for all of these immense and intense and exciting proposals, and hope you like them. Thank you. Thank you, Hemant, for this great talk. Now, let's jump to the polls. What type of proposals do you like the most? I hope you all answer.
Syntax Sugar, Questions, and Committee Experience
Syntax Sugar is the winner with 32%, followed by Fresh Paradise with 30%, New Operator with 20%, and New Method on the prototype with 16%. The popularity of Syntax Sugar is not surprising, as it simplifies programming constructs and makes the code more precise and concise. Now, let's move on to the questions. Bartos asks about the use of the add function, which allows for retrieving elements based on indices, including negative indices. Gianpo wonders if there is a voting process for the proposals, to which the answer is no, but there are forums and open discussions for feedback. The committee does not specifically consider TypeScript compatibility when vetting proposals. Being part of the committee is an amazing experience, surrounded by smart individuals who bring in different perspectives and edge cases. There is a lot to learn from these interactions.
And the winner is Syntax Sugar with 32% followed by Fresh Paradise with 30%, New Operator by 20%, and New Method on the prototype by 16%. Do you find this interesting, Hemant, or do you find this surprising? What are your thoughts about this? Yeah, it's pretty interesting. And also, it happened to be the very first options in the questions. And people normally like Syntax Sugar because it kind of makes programming constructs easier and the core looks more precise and concise. And that's why I feel the maximum has gone to Syntax Sugar, and we are still seeing it's going up. Okay, nice!
And now let's jump into the questions. Bartos is asking, apart from the negative indices, what is the use for the case of add function? Yeah, it's not only just negative indices, you can also add any index you want. And if you look into the DOM APIs, as I mentioned in the talk, it also has the similar approach of getting the index from the mode list. So it helps you to get an element at that appropriate index easily. And negative index is also an add-on to it where you could go and fetch the element in, say, at the last and pick it up. So that's the advantage. Okay, thank you.
Gianpo asks, it is possible to vote for those proposals? Or is it a job for the RF committee? Well, yeah. Apart from the committee, people don't really get to vote for the proposals, but there are too many forums where you can discuss about proposals and share your ideas and thoughts. And there are also at times a tweet, which turned into a proposal and got implemented. So it happens all in the open, but the meetings happen in closed environments, but the notes are always open. Folks can read the notes and we can provide feedbacks on the proposal, but not really voting, because voting happens in a room where we have implementers who get the, who have the authority to say, hey, this might cause an ambiguity for this is pretty complex to implement in a browser, who have more idea on how the implementation should be done. And apart from that, all the members of the committee get the rights to vote for the versions. Okay, thank you.
The next question is from me. How is to be in the committee? Is it fun? Is it difficult? How is interacting with the other people? Like the proposals, the votes? In general, how do you like it? Well, it's amazing like being surrounded with a bunch of very smart people and at times we have Brenda and I, the man himself in the room and it's really humbling and you know the people are so super smart and they kind of bring in edge cases to scenarios. I remember one of the conversations we were having about dates. One gentleman brought up a particular date format we had never heard where the months varies and the dates varies kind of a thing. So they can also like just quote the ISO specifications and without even looking and referring and so like amazing bunch of folks and there's so much to learn highly influenced by all of the smart people in the room. That sounds super amazing.