Skip to content
This repository was archived by the owner on Jan 25, 2022. It is now read-only.

The # is confusing. Should be private instead. #262

Closed
danieldogeanu opened this issue Aug 7, 2019 · 19 comments
Closed

The # is confusing. Should be private instead. #262

danieldogeanu opened this issue Aug 7, 2019 · 19 comments

Comments

@danieldogeanu
Copy link

danieldogeanu commented Aug 7, 2019

Can I make the case against using the # sign to denote private fields?

Since the language is also getting a static keyword, it would be consistent to also get a private keyword for private fields. The # sign just makes the language a lot more confusing than it already is.

Using the private keyword will also make it consistent with other C-like languages and it would be easier for developers to use it.

I don't have a problem with the private fields per se, but I consider things should be a little more readable. The # sign is not readable at all.

Please take this into consideration. Thanks.

@jhpratt
Copy link

jhpratt commented Aug 7, 2019

Please read the FAQ.

@danieldogeanu
Copy link
Author

Please read the FAQ.

I did and I still don't agree with the use of #. I consider that developers should in fact be able to use the this keyword to access private fields too, and that the language should take care of accessing those fields, or throw errors when they're not supposed to access them.

I agree that it would be harder to implement, but let's not just duct-tape features to JavaScript. Especially because it already has its fair share of that.

@jhpratt
Copy link

jhpratt commented Aug 7, 2019

or throw errors when they're not supposed to access them

That would violate the hard privacy requirement that the committee has set.

Frankly, this issue has been discussed to death, and I highly doubt you're going to bring anything new to this argument, given that your argument so far is "I don't like it" and "it's not like other languages". The committee is aware, and they decided this was the best way forward.

@ljharb
Copy link
Member

ljharb commented Aug 7, 2019

It has nothing to do with being harder or easier to implement. If you can observe the field from outside, it’s not private - so throwing on a string property is not acceptable.

@danieldogeanu
Copy link
Author

Frankly, this issue has been discussed to death, and I highly doubt you're going to bring anything new to this argument

I see. Well, you're right. I tried my best and at least said something about it.

given that your argument so far is "I don't like it" and "it's not like other languages"

My argument isn't "I don't like it", my argument is pure readability and consistency.

@rdking
Copy link

rdking commented Aug 7, 2019

@danieldogeanu As one of the people who argued this into the ground, even I eventually ended up agreeing that this.field is untenable. However, (and guys, I'm not re-opening this argument) it was never the case that access via this (as long as some other operator than . is used) or use of private was impossible or otherwise untenable. It's just that despite the fact that the semantics surrounding ES6 class is different from that of other languages, TC39 somehow got it stuck in their heads that private x always implies this.x. Nothing requires it to be true for ES though. Even another operator would suffice (many have already been offered and refused).

Bottom line is that there is no logical reasoning behind their decisions in this matter. There is, however, rational reasoning backed by a particular emotional stance. Because of this, there is no reasonable approach to dissuade them from this course of action. It isn't that your perspective isn't shared by many, but rather that this perspective doesn't agree TC39's "concensus". They've decided that the issues important to those of us holding this view are not issues with as great a value as they ones they've considered. Or from your post, "pure readability and consistency" is not as important as the fallacious assumption that "private x implies this.x".

@danieldogeanu
Copy link
Author

@rdking I would be perfectly fine with using private.x instead of this.x to access the private fields, if this.x is off limits. In my opinion it would be even less confusing.

@ljharb
Copy link
Member

ljharb commented Aug 7, 2019

That wouldn’t allow for accessing private fields on other objects besides this, which is necessary for usage with instances in static methods.

@rdking
Copy link

rdking commented Aug 7, 2019

Like I said, many such options were tried and defeated:

  • private.x or private(obj).x: Solves the problem @ljharb mentioned, but considered not ergonomic enough
  • private x && this#.x where this# had the same meaning as private(this): Shot down due to the desire that # should appear to be part of the name even though it's not, to force an artificial declaration symmetry.
  • private x && this::x: lacks the artificial symmetry, and violates the invalid implication that private x implies this.x

There were many others as well, but the reasoning was mostly along these lines.

@ljharb
Copy link
Member

ljharb commented Aug 7, 2019

The # is absolutely and definitively part of the name.

@rdking
Copy link

rdking commented Aug 8, 2019

@ljharb You may say so, but the proposal's author (@bakkot) disagrees with you, or at least he did when I last discussed the issue with him. If that has changed since then, I can accept that. If not, then by your own words, you are incorrect since (as you previously told me) the intention of the elements of the proposal are up to the proposal's author.

@ljharb
Copy link
Member

ljharb commented Aug 8, 2019

The proposal has many authors, but fair enough.

@bakkot
Copy link
Contributor

bakkot commented Aug 8, 2019

I'm not really sure what you're talking about. I refused to classify it as "part of the [[IdentifierName]]", because IdentifierName is a specific production in the grammar which does not include #, but that's all. I did not say that # was not part of the name of the field.

@rdking
Copy link

rdking commented Aug 8, 2019

Am I not correct in saying that at least at present (prior to class-fields reaching stage 4), all variable and property names in ES are classified as an [[IdentifierName]]? Even a Symbol is an [[IdentifierName]]. By refusing to classify # as part of an [[IdentifierName]], you are likewise claiming that any name prefixed with # is neither a variable name nor a property name. But if it's not a property name, then how is it accessible via this. since operator . is used to access the properties inside the property bag of the LHS argument this?

Can you see how this begs the question of what #foo actually means? I don't wish to pursue that though, since I'm already aware of your stance of it being "something different" with no intention to clarify.

@rdking
Copy link

rdking commented Aug 8, 2019

To all TC39 members reading the above post:
The reason I have pressed so ardently for clarity of both requirements and intentions is because of experience with other languages. The excessive complexity of languages like C++ partially came about as a result of the designers and maintainers leaving so many issues unclearly defined and up to the compiler developers. This led to many compilers supporting the same feature in incompatible ways that, although seemingly of little comparative importance at the time of design, led to major incompatibility issues for code designed to take advantage of certain optimizing situations.

Leaving such an unclear element like whether or not # is a name element and thus part of an [[IdentifierName]], or an operator, or something else entirely so thoroughly up in the air is only inviting the same kind of problems to creep into ES. However, feel free to keep ignoring the lessons learned in other languages if that is what you wish to do.

@ljharb
Copy link
Member

ljharb commented Aug 8, 2019

As was said in the linked thread, it’s a brand new thing. It’s also a thing hardly any other languages have. The # is part of the name, it’s not part of an IdentifierName, and it’s accessed only with dot.

This has nothing to do with unspecified behavior; it seems like you’re talking about mental models?

@bakkot
Copy link
Contributor

bakkot commented Aug 8, 2019

The spec is unambiguous, in part because it is not defined in terms of things like "what is part of the name of a field" (unless it has given explicit, unambiguous definitions to each of those words). And this proposal introduces no new implementation-defined behavior (meanwhile, elsewhere we are working on cutting down on such behavior where it currently exists). I don't think there is much risk of that here.

Also, I don't know what "Symbol is an [[IdentifierName]]" means. IdentifierName is a grammar production; Symbols are ECMAScript language values. That comparison is a category error.

Anyway, this is pretty off topic. If you want to keep discussing this, please make another issue or open a thread on the discourse.

However, feel free to keep ignoring the lessons learned in other languages if that is what you wish to do.

Please don't do this. No one is deliberately ignoring anything. We have a disagreement about terminology.

@rdking
Copy link

rdking commented Aug 8, 2019

Maybe "disregard" would have been a better choice than "ignore". As I've said before, TC39 gets full marks on at least trying to cover all the bases. In either case, since I often cross terminology in ways that should not be done, I'm going to pour through the spec 1 more time to make sure that what I say in discourse carries the intended meanings.

@littledan
Copy link
Member

Thanks for your feedback.

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

6 participants