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

Consider using private keyword AND sigil for declaration #53

Open
dalexander01 opened this issue Sep 20, 2016 · 120 comments
Open

Consider using private keyword AND sigil for declaration #53

dalexander01 opened this issue Sep 20, 2016 · 120 comments

Comments

@dalexander01
Copy link

Basically bringing back @wycats proposal: https://github.com/wycats/javascript-private-state

class {
  private #data1;   // data1 is the name of a private data slot
                    // the scope of 'data1' is the body of the class definition 
  constructor(d) {
    // #data1 has the value undefined here

    // # is used to access a private data slot
    // #data1 is shorthand for this.#data1
    #data1 = d; 
  }

  // a method that accesses a private data slot
  get data() {
    return #data1;
  }
}

I am not going to cover the importance of using the sigil for access as this has been explained ad nauseam in other issue threads.

I think using the private keyword to indicate privacy and the sigil to indicate how to access fields makes the code easier to read and provides some linting and IDE advantages over just using the # to indicate privacy and access.

Some call using both redundant but I do not think so at all.

private #data1 simply means that we have a field called data1 that is private, that you access with this.#data1 or #data1. Everything you need to know you can find in the declaration. Where as without the private keyword, readers and coders would have to remember what the sigil means.

The sigil doesn't indicate privacy, it only indicates how to access the field. This thought process opens up the possibility for other access modifiers to possibly share sigils if needed.

For example:

private #field1;
protected #field2;

Here you have 2 different fields with different access modifiers, but both accessed through the same sigil.

It would also lean to more consistent code and make more sense in the case of another access modifier not needing a sigil for access:

private #field1;
protected field2;

vs

#field1
protected field2;  

I think the above would be totally unintuitive.

@zenparsing
Copy link
Member

I would only be comfortable with this if the keyword were optional. If we start without the keyword, we can add it as an optional keyword at a later time, right?

@dalexander01
Copy link
Author

I would only be comfortable with this if the keyword were optional. If we start without the keyword, we can add it as an optional keyword at a later time, right?

I don't think the keyword should be optional since I think the sigil should indicate how to access, not visibility. Consider wycats example of protected slot definition and access:

class Base {
  private #slot1;
  protected #slot2;

  constructor (s1,s2) {
    #slot1 = s1;
    #slot2 = s2;
  }
 }

Without the keywords you would need different sigils and end up with sigil soup. I think the above is a lot more readable and to the point.

@zenparsing
Copy link
Member

It's fairly typically to have a default "access modifier" in OOP languages, though.

Without the keywords you would need different sigils and end up with sigil soup. I think the above is a lot more readable and to the point.

That's not true. This is reasonable, I think:

class C {
  #slot1;
  unprotected #slot2;
  constructor(s1,s2) {
    #slot1 = s1;
    #slot2 = s2;
  }
}

@dalexander01
Copy link
Author

dalexander01 commented Sep 20, 2016

It's fairly typically to have a default "access modifier" in OOP languages, though.

Without the keywords you would need different sigils and end up with sigil soup. I think the above is a lot more readable and to the point.
That's not true. This is reasonable, I think:

class C {
#slot1;
unprotected #slot2;
constructor(s1,s2) {
#slot1 = s1;
#slot2 = s2;
}
}

I assumed due to the nature of this proposal and the fact that there is no corresponding "public" keyword that the default visibility would be public as it is today. The public keyword would not require a sigil so it's a moot point.

Maybe I didn't understand what you mean by "optional", but in the code above if the keywords were optional wouldn't this be possible?:

class C {
   #slot1;
   #slot2; // is slot2 unprotected or private here?

In the case of possible private and protected access, if the keywords were optional, you would need 2 different sigils. You would end up with sigil soup, something like:

class A {
   #field1;
   @field2; // or whatever other sigil you want to use for protected

   constructor(field1, field2) {
      this.#field1 = field1;
      this.@field2 = field2;
   }
}

You could use a protected keyword instead of sigil, but then it raises the question of why can't we also use the private keyword instead of a sigil? Using a protected keyword and sigil for private makes things inconsistent and less intuitive in my opinion:

class A {
     protected field1;
     #field2; // wtf why can't I just use private field2 here?
}

Separating the declaration with an access modifier and a sigil to represent how to access the field, seems to be the most straightforward and most intuitive solution in my opinion.

@zenparsing
Copy link
Member

Maybe I didn't understand what you mean by "optional", but in the code above if the keywords were optional wouldn't this be possible?

I was thinking of C#, for example, where if there is no access modifier it is assumed to be "private".

In the case of possible private and protected access, if the keywords were optional, you would need 2 different sigils

Why do you think that?

@dalexander01
Copy link
Author

dalexander01 commented Sep 20, 2016

Ok, I thought you meant that all access modifier keywords would be optional. If that was the case then all access modifiers would require different sigils.

I think we should keep the default access public like it is today. In my opinion an access keyword should be there for any possible declarations that require a sigil. It literally tells the readers what the sigils mean which makes the code more readable and self documenting, and less jarring and awkward. IDE's would also be able to code complete what sigils should come next after the access modifier. Linters would be able to detect sigil mismatches, reducing errors.

I think you also may get better reception to the proposal if the private keyword was there from the jump.

private #field;

I think you would get a lot less pushback explaining why you need the sigil in the above case, opposed to explaining why we can't intuitively use the private keyword like a lot of people are asking for. I think this is a compromise that most could live with given the limitations of the language and the unwillingness to make property access any slower.

@hitmands
Copy link

hitmands commented Sep 30, 2016

Personally I thikn there are few reasons to use sigils instead of keywords.

keywords such as private, protected etc. make them more scalable and familiar because is a common among languages.

@dalexander01
Copy link
Author

Personally I thikn there are few reasons to use sigils instead of keywords.

keywords such as private, protected etc. make them more scalable and familiar because is a common among languages.

The champions of this proposal have concluded that access of private fields has to be done via a sigil ie this.#field or #field for performance reasons. You can read all about this decision here: #14

My proposal is to use the private keyword along with the sigil for declaration to bring back some of the familiarity and readability you speak of.

@littledan
Copy link
Member

I think declaring as private #foo is not unreasonable, though I wouldn't characterize the need for a sigil on access as "for performance reasons" entirely. @allenwb has also advocated for this syntax. I'll make sure to bring this up as an option for the committee when proposing to advance to Stage 2.

@indolering
Copy link

@littledan What non-performance reasons are there?

@littledan
Copy link
Member

This is discussed in other threads. Let's let this thread stick to whether we should use "private #x" or "#x" as the declaration form.

@Jordan-Hall
Copy link

I would second this but can we change the sigil to _. Many full stack developers usually use underscore when using getters and setters. I also this private should be mandatory to make it clear that we are taking about a private field

@bakkot
Copy link
Contributor

bakkot commented Nov 27, 2016

The sigil would need to be something which is not an IdentifierStart, so _ wouldn't work.

@ljharb
Copy link
Member

ljharb commented Nov 27, 2016

It would also be a breaking change to code that has _ which is currently fake-private (ie, fully public) to suddenly become truly private.

@Jordan-Hall
Copy link

@ljharb I can't see that being an issue. Plus if we force the private key work then it's all good

@ljharb
Copy link
Member

ljharb commented Nov 27, 2016

@Jordan-Hall it's an issue for the same reason that when authors remove _-prefixed properties, things that depended on them break. npm broke node once by doing that, if i recall.

@Jordan-Hall
Copy link

Can we not have an interm solution to solve this.

Even though I agree and been saying for years that javascript needs private fields and methods can we not just support this # sigil but require the private keyword until we can remove the sigil.

@ljharb
Copy link
Member

ljharb commented Nov 27, 2016

The reasons to include a sigil will not change - if a sigil is included now, it will be included forever. This issue is about using both the sigil and the private keyword (also forever).

@Jordan-Hall
Copy link

Tbh I really don't get why we need sigil. I for one think it should be the private keyword. If that means having both then so be it.

But question is why can't we make this keyword smarter

@zenparsing
Copy link
Member

When you say "smarter" you're implicitly introducing notions about static typing, though.

When you attempt to fit those notions into a fully dynamic system like JS, you end up with unacceptable compromises in order to overcome the lack of static type information.

@zenparsing
Copy link
Member

I for one am 100% against an unnecessary "private" keyword. Although to be fair I'm also 100% against using # for the sigil.

@littledan
Copy link
Member

Let's leave this thread to discuss whether we should use an additional private keyword in the declaration. There are other bugs to discuss the sigil choice and whether one is needed (which have been closed).

@Jordan-Hall
Copy link

@littledan the whole point of my comment was to say we should use private with sigil. Just think we need a better sigil

@littledan
Copy link
Member

It appears that neither _ nor @ are available at this point. We could go with others, such as ^ or & but they have ASI hazards and therefore are suboptimal.

@Jordan-Hall
Copy link

@littledan whats wrong with _ I know lodash uses it but surely we can make it check for Private keyword.
What about using '!'. But TBH more I look at the sigil # kinda looks ok. But only if we force the private keyword

@littledan
Copy link
Member

Unary ! already means not in JS.

@Jordan-Hall
Copy link

@littledan yea good point. I forgot about ! without using '!=' I see the problem now with the Sigil. No matter what symbol it wont be possible to use unless not already defined. But are we not walking into a trap that soon they wont be a symbol left?

But on topic I think Private for now should be optional. Otherwise we run into the issue of developers wanting to be more strongly typed like TypeScript

@zenparsing
Copy link
Member

But are we not walking into a trap that soon there wont be a symbol left?

That is a valid concern.

@littledan
Copy link
Member

@Jordan-Hall What do you mean by optional? All new language features are optional to use or not use.

@jhonnymoreira
Copy link

Instead of using special chars to define private and protected vars, why not use just a keyword private or protected and the code section below assume the behavior of the keyword?

@dresende
Copy link

And I love the FAQ mentioning is perfectly legal Java repeatedly. private x is perfectly legal Java, why not? 😄

@bakkot
Copy link
Contributor

bakkot commented Jun 16, 2017

@nuragic

BUT let me fruitfully disagree about the supposition that we'll get used to #.

OK, let me say rather that in my experience, people do get used to the sigil after some amount of exposure. I won't assert that you will, necessarily, but many people have.

@dresende

How is this different from now?

Because the declaration matches references. private x = 0 implies that access will be this.x much more strongly than does #x = 0 - indeed, given that y = 0 creates a field accessed by this.y, I'd think it very natural that #x = 0 creates a field accessed by this.#x.

I bet this proposal will bring much more bugs like this:

I do not expect very many people to create public and private fields of the same name, except possibly for accessors (for which the bug will be fairly obvious). Yes, it's a hazard, but I believe it's much less of one than if declaration were private x and access were anything other than this.x.

It's not possible to have that.#x,

Er... no, that's not true. It is a fundamental part of the design of private fields that one instance of a class can access the private fields of another (if given the power to do so by the class).

private x is perfectly legal Java, why not?

That is the main question which the FAQ seeks to answer.

@dresende
Copy link

class Foo {
	constructor() {
		y = 1
	}
}

new Foo

Correct me if I'm wrong. Will this create this.y?

@bakkot
Copy link
Contributor

bakkot commented Jun 16, 2017

No, but under the current proposal,

class A {
  #x = 0;
  y = 1;
}
new A

will create this.#x and this.y.

@dresende
Copy link

You said given that y = 0 creates a field accessed by this.y, but it seems we're actually assuming both proposals will get introduced simultaneously. I really hope not, sorry.

@bakkot
Copy link
Contributor

bakkot commented Jun 16, 2017

@dresende They're currently part of the same proposal, after many years of discussion. Why do you hope not?

@dresende
Copy link

Because so many people seem to dislike the # prefix for private variables and there seems to be an inercia to just go ahead and keep it that way.

@ljharb
Copy link
Member

ljharb commented Jun 16, 2017

I don't know where you're getting "so many"; I'm sure some will dislike whatever's chosen, and "like" is only really useful when all other things are equal. The FAQ explains why all else is not equal, which means "like" shouldn't imo get much weight.

@littledan
Copy link
Member

@dresende It's true, a lot of people dislike the # prefix. I believe you will not be the only person who's upset or confused by this feature, or any particular new feature we add. However, until you present an alternative that works, this discussion is not as productive as it could be.

We have to make a cost-benefit analysis. I believe the benefit of private fields is large. The cost is implementation burden and complexity of the language model, which includes people getting confused sometimes. I think we can address this by doing a good job on the educational materials; @thejameskyle, for one, wrote an excellent blog post explaining the feature, but we'll need more. We can decide it's not worth the tradeoff, though, and drop this feature.

But we cannot just magically say "OK, we'll do it just like Java syntax" because we've thought through the implications of that, and it seems intractable to combine with the rest of the language. And a lot of ink has been spilled to explain this, in this thread and in the FAQ. We could go with a different alternative (that I can't think of personally), or drop the feature, or leave it as is; those are the choices.

@nuragic
Copy link

nuragic commented Jun 17, 2017

If you had a choice between the private fields proposed here, and no addition, which would you prefer?

@littledan Tough question: if the choice would be irreversible, then my vote would be no addition. I'm sorry, really, I appreciate a lot your efforts to make this happen, don't get me wrong. Maybe it's a personal feeling, also incentivated by some thread I saw about built in protected fields not likely to land in the future... So at this point, I think that we can perfectly survive using WeakMaps, that's what I'd use, and I think that's perfectly legit within the JS style of doing things. If is not possible to create a whole unified ergonomic solution, things might turn worst then the actual scenario (which IMO is too much friction/hostility against the feature) on the long run. But you know, it's just like, my opinion man. Finally, on my side I'd like to say sorry for the extra noise, wish to have more time to study the language internals and being able to provide more value to the discussion; until it will happen, I'm aware I've already said enough from my humble developer perspective so... 🤐! At the end of the day I'll be fine with whatever will decide the committee. ❤

@iddan
Copy link

iddan commented Jun 17, 2017

The thing is we don't decide as a community: champions are choosing for us. Until we'll have a way to vote for specs we have no voice in the committee. I call for a change.

@dresende
Copy link

@littledan I would prefer have nothing. I live with JS since Netscape and never missed this or classes by the way. As I said before, I prefer not to have a feature than have something that looks like a comment.

@dresende
Copy link

@ljharb I don't know how you measure many, the only way I see right now is looking at +/-1 at many already closed issues here. Maybe you could open a public poll at Medium or something? That way the community (or some significant part of it) could say something..

@ljharb
Copy link
Member

ljharb commented Jun 19, 2017

@dresende There's just no way to reach a significant part of the community through social media, although we certainly could try to reach a larger number. However, "looks like a comment" is very subjective and generally only applies to people coming from very specific languages - in JS, the only things that should look like a comment are //, /*, <!--, and -->, because that's what means "comment" ¯\_(ツ)_/¯

@littledan
Copy link
Member

I've tried Twitter polls before, but any feedback from that was laughed out of the room in the past. I'm not sure how to get a representative sample. But I'd really love to collect more feedback. @dresende , @iddan , do you have any ideas for how to do this?

It's great to get comments on GitHub, and I feel like good changes to this proposal were made based on that, but at the same time, when an aesthetic problem is raised, it's really hard to determine how bad it is (since these things are subjective, and the detractors are more likely to comment). I've seen some positive feedback, e.g. here (even if the example was a little mistaken).

In C/C++, # does not indicate a comment, but instead a very significant element. Maybe people are more likely to come from Python to JavaScript than C/C++ to JavaScript (not sure how to quantify that, but there are definitely many people in the latter category), but what I've heard from educators is that many people are actually learning JavaScript as a first programming language.

@dresende
Copy link

I'm not sure, I suggested Medium because I read many technical posts and so I assume there's a big tech community there. It had to be someone with relevance (with enough followers) to help reaching a significant amount of people. But I don't know. For me, # is always a comment (and I don't like Python). I started with C/C++ and still look at that as a comment. Remember shell scripts and configuration files, many assume that as a comment.

@bterlson
Copy link
Member

bterlson commented Jun 20, 2017

@littledan as someone who has also done a few twitter polls and raised them with the committee, I don't think "laughed out of the room" is really correct. It is only a single data point and making decisions based solely on one poll (or the number of up/downvotes on GitHub) is not how you design a good language and so it is understood in that context. I think it's still useful data, personally (especially the replies).

@iddan
Copy link

iddan commented Jun 20, 2017

@littledan I'm proposing an official voting site (even just a minisite for this proposal). Been hacking around to make one with the @github reaction API

@littledan
Copy link
Member

@iddan That'll be great, I'd love to have a good place where I can put questions like this to a poll for some more feedback, in addition to whatever we can get from Twitter.

@glen-84
Copy link

glen-84 commented Jun 20, 2017

This thread seems to have gone way off topic.

If you want to discuss the use of the sigil, then I would suggest posting to #14.

@littledan, maybe that issue should be re-opened, to avoid the same subject being brought up repeatedly? (you could label it declined or archive or something)

@littledan
Copy link
Member

littledan commented Jun 21, 2017

I doubt reopening it will prevent people from posting to all sorts of bugs to raise it again. It was raised across many bugs while they were all open. I'd prefer to reopen it only if we can really consider it again, but there are some pretty strong arguments in the FAQ for why it would be hard to consider.

@gynet
Copy link

gynet commented May 11, 2018

I think if we have to use the prefix # by the limition, it would be better to add the "private" keyword as the declaration for two reasons. First, the "private" is already a reserved keyword in JavaScript, and the hard private, the poposal targeting thing, is just the "subset" of soft private, it would be make sense and worth to add the "private" keyword, in case someday we want soft private, just like what Typescript is doing, we should think further about this scenario. Sendond thing would be Ergonomics, beside subsjective tastes, most ppl don't like the prefix is because it's hard to understand the syntax if they don't know, different as other new syntax proposed, for access level, as far as I konw, most of popular programing languages don't use prefix to indicate access level. @littledan

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