Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consider syntax for tuple literals: (['a', 2]) // [string, number] #9217

Closed
zpdDG4gta8XKpMCd opened this issue Jun 16, 2016 · 21 comments
Closed

Comments

@zpdDG4gta8XKpMCd
Copy link

zpdDG4gta8XKpMCd commented Jun 16, 2016

Problem

There is no way to get a tuple value without explicit type annotation:

var tuple = ['hey', 1]; // (string|number)[]

Solution

Add new syntax for tuple literals:

var tuple = (['hey', 1]); // [string, number]

related #9216

@blendsdk
Copy link

would this help?


type tuple = [boolean, number, string];

var t2: tuple = [1, 2, 2]; // error
var t3: tuple = [true, 1, "abc"];  // ok

@zpdDG4gta8XKpMCd
Copy link
Author

this is stated as a problem that is sought to be solved

There is no way to get a tuple value without explicit type annotation:

meaning that you example only works thank to explicit type declaration which i wish could be avoided

type tuple = [boolean, number, string];

@blendsdk
Copy link

Ah..... I misread the question. I am inclined to say type tuple = Array<any> but then it is not a tuple anymore.

@mhegazy
Copy link
Contributor

mhegazy commented Jun 16, 2016

we have talked about this before, we could not come up with a proposal that works and looks right.. some of the options considered

  • special syntax, var x = [| 1, 2 |]
  • special function, var y = tuple(1,2)
  • a type annotation, var z: [...] = [1,2]

nothing seemed palatable to be frank.

@zpdDG4gta8XKpMCd
Copy link
Author

zpdDG4gta8XKpMCd commented Jun 16, 2016

why would not this work: (['hey', 1])?

  • works fine with the existing syntax
  • highly unlikely to be a breaking change
  • doesn't affect JavaScript semantics at all (can be executed as written and will work as expected)
  • resembles a object-literal-literal x => ({value: x})

@mhegazy
Copy link
Contributor

mhegazy commented Jun 16, 2016

this is rather subtle. looking at it i would not guess, and if i did it by mistake i would not be able to see why it is working any differently.
For a while contextual type did not go through parenthesized expressions, and ppl tripped over it consistently.

@zpdDG4gta8XKpMCd zpdDG4gta8XKpMCd changed the title add syntax for tuple literals consider syntax for tuple literals: (['a', 2]) // [string, number] Jun 16, 2016
@ahejlsberg
Copy link
Member

We did at one point consider the ([x, y]) syntax for tuples, but as @mhegazy says, we thought it too subtle. Someone looking at ([x, y]) would have absolutely no intuition that it produces a different type than [x, y].

@zpdDG4gta8XKpMCd
Copy link
Author

my few centes, speaking for myself:

  • right now seeing something like ([]) rather than [] looks strange to me, so it's a red flag anyway
  • this pattern is unlikely to be used intentionally, yet it's very likely to be by mistake
  • if so, why won't we take advantage of something being no use
  • it's ok for new features to call for new capabilities, this is how it usually goes

@dsbl41
Copy link

dsbl41 commented Jun 16, 2016

FWIW I kind of like @Aleksey-Bykov proposal.
I would have the intuition that ([x, y]) is different from [x, y] as it looks similar to an arrow function with a concise body returning an object literal:

var f = x => {}; // returns void
var f = x => ({}); // returns {}

With the proposed ([x, y]) syntax:

var f = x => ['hey', 1]; // returns (string|number)[] type
var f = x => (['hey', 1]); // returns [string, number] type

@ntrrgc
Copy link
Contributor

ntrrgc commented Jun 16, 2016

In my projects I use something like this:

export function tuple<T1>(value: [T1]): [T1]
export function tuple<T1,T2>(value: [T1, T2]): [T1, T2]
export function tuple<T1,T2,T3>(value: [T1, T2, T3]): [T1, T2, T3]
// ...
export function tuple(value: any[]): any[] {
    return value;
}

The usage is very simple and explicit:

var myTuple = tuple(['hey', 1]); // [string, number]

@zpdDG4gta8XKpMCd
Copy link
Author

@ntrrgc this is my current workaround: #9216 (comment)

@aluanhaddad
Copy link
Contributor

I don't like the analogy with the arrow function returning object literal syntax because that syntax itself is kind of a hack to get around an issue with how arrow functions are specified in ECMAScript.

That said, it's a useful hack but it has no impact on the type of the object literal, it has an impact on the type and value of the function, and no one writes them in parentheses except to return them from expression bodied arrow functions.

@zpdDG4gta8XKpMCd
Copy link
Author

zpdDG4gta8XKpMCd commented Jun 16, 2016

like it or not:

  • it already happend and can't be fixed
  • it does what it does, and people get used to it
  • it's better than nothing

so it's easier to get along with it than deny

@mhegazy
Copy link
Contributor

mhegazy commented Jun 16, 2016

i disagree with the "better than nothing". i still find this fairly confusing, let a side undiscovered.

@zpdDG4gta8XKpMCd
Copy link
Author

@mhegazy i was talking about x => ({ value: x }) syntax that is used for returting object-literals in lambdas that @aluanhaddad happened not to like

of which, better than nothing means there is no better syntax for object literal results in lambdas (aside from the statements), and this is something no one can change anymore, despite being ugly, it works for a lot of people

we've seen it, we hated it but we ate it, and it worked out

so there is a precedent

@ahejlsberg
Copy link
Member

@Aleksey-Bykov I think where the analogy breaks down is that { value: x } and ({ value: x }) have the same type, whereas [x, y] and ([x, y]) would have different types with what you're proposing.

@zpdDG4gta8XKpMCd
Copy link
Author

@ahejlsberg, I admit, the syntax is not ideal, and what you said is definitely a weak point of the idea, at the same time it has a number of strong points, as far as i can tell, that were also mentioned

to my defence: the fact that ([]) and [] currently mean the same is a waste of valuable syntax, because you don't usually see ([]) in the wild, all I am saying is that it might get a better use

@aluanhaddad
Copy link
Contributor

@Aleksey-Bykov I was objecting to the analogy for the exact reasons that @ahejlsberg mentioned. I was not objecting to the work around syntax for returning object literals from expression bodied arrow functions.

I think it's a shame that expression bodied arrow functions require a kludge to work with object literals but the syntax could be worse.

I'm saying the analogy is flawed.

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Jun 17, 2016

After re-reading my comment I realize I could have been clearer. I was indeed saying that it's not great to follow the precedent of a syntax that is a hack in the first place.
I was also trying to get across that the use of parentheses is completely different in that context because it alters the function returning the value, not the value itself.

@Artazor
Copy link
Contributor

Artazor commented Jun 23, 2016

I know about "not playing at the expression level syntax" rule...
but just as a fantasy:

x = <>[ 1, 'a', true ]  // or [ 1, 'a', true ] as <> - type strongifier
x = #[ 1, 'a', true ] // - AFAIK # now is invalid symbol. treat #[ - as a single delimiter
x = [: 1, 'a', true :] // symmetric smiley brackets

@zpdDG4gta8XKpMCd
Copy link
Author

Closing in favor of #10195

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants