tc39 / proposal-record-tuple

ECMAScript proposal for the Record and Tuple value types. | Stage 2: it will change!
https://tc39.es/proposal-record-tuple/
2.48k stars 62 forks source link

Why mixing immutability and tuples ? #371

Open houd1ni opened 1 year ago

houd1ni commented 1 year ago

Hi. This proposal looks like hard mixing of two different and distinct ideas: immutability and tuples. The last could be used in functions to return more that one value, for example, without need to create a whole new object, like in golang. And immutability wrappers or so could exist in a different proposal without specific syntax to not to mix things up. Now we already have some of the mix, by having immutable strings (that however could be optimized by jit while replacing) and anything else. Why develop this ?

phryneas commented 1 year ago

The introduction of the proposal calls tuples an immutable array-like structure.

And that's probably already the answer to your question: if you leave the immutability away, you end up with Arrays. Which already exist.

If you want to return two values from a function, you could already today return [firstValue, secondValue]. There's no need for a new feature to enable that.

The feature of JS tuples will be the immutability - and as a consequene the ability for cheap shallow equality checks.

houd1ni commented 1 year ago

Thank you for the quick answer. Yet it does not answer the question. I'll try to split it into two:

My motivation is to have something like golang tuples that feel simple and could be made and destructured with no cost. And to not to make things harder to remember and use.

UPD: By historical nuance, that kind of destruction assignment issue barely came up because initially there were no Promises and, therefore, we used callbacks with arguments needed. Now it's in demand: const [err, data] = await request(...). UPD2: I understand that it's handy when one writes Redux, but if she does not, and, maybe came from other languages, even haskell, it might be confusing even more than it was decade ago.

acutmore commented 1 year ago

Every time I return an array of fixed small length from a function, then right after call I immediately destruct the array, I feel I make GC work more than it should. Sometimes it costs, for example in long loops.

It sounds like you are wanting something which has a fixed memory size and is allocated on the call stack. These types of details are at a much lower abstraction than what the ECMAScript specification operates at. This works both ways, if a golang style tuple was added to JS implementations would be free to allocate this on the Heap and use GC to collect it; but also existing JS engines are also free to optimise functions that return arrays which are immediately destructured. Similar to how ECMAScript doesn't have syntax for function inline hints but many JS JITs will inline functions.

Another option is to use an ahead-of-time optimising compiler such as https://developers.google.com/closure/compiler which can transform JS into more optional forms, leaving the original source code to write more idiomatic JS which expresses their intent.

houd1ni commented 1 year ago

@acutmore Closure makes a little bit different "optimizations" 😄 (pic below)

I've seen google's v8 presentation, they say, if a function returns an object, they cannot optimize it because it "escapes" the function scope. Probably it is because the array could be then modified somehow, and the optimizer could not track it for some reason. Hence, if a tuple is immutable by definition, it finally can be optimized well. Does the deep immutability constrain have impact on the optimization possibility ?

Anyone from V8 team ? Should you/we consult them to be sure in optimization possibilities before adopt such a big feature ?

image

Andrew-Cottrell commented 1 year ago
Off topic & FYI: if the Closure Compiler `@language_out ECMASCRIPT_2015` option is specified ```javascript // ==ClosureCompiler== // @compilation_level ADVANCED_OPTIMIZATIONS // @output_file_name default.js // @language_out ECMASCRIPT_2015 // @formatting pretty_print // ==/ClosureCompiler== // ADD YOUR CODE HERE const damn = (a, b) => { return [a, a+b] } function hello(name) { const f = window.f const [a, b] = damn(f, 6) alert('Hello, ' + name + a+b); } hello('New user'); ``` then Closure Compiler doesn't transcompile [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) and the optimised output is reduced to ```javascript 'use strict'; var a = window.f; const [b, c] = [a, a + 6]; alert("Hello, New user" + b + c); ```