New private names proposal
brendan at mozilla.org
Tue Dec 21 23:58:46 PST 2010
[Resending as you did to the right group, although I filter both to the same folder and prune dups. Whee! /be]
On Dec 21, 2010, at 10:22 PM, David-Sarah Hopwood wrote:
> On 2010-12-21 22:12, Brendan Eich wrote:
>> On Dec 20, 2010, at 11:05 PM, David-Sarah Hopwood wrote:
> Please retain all relevant attribution lines.
Oops, sorry about that.
But really, lighten up. I don't think anyone mixed up your words for mine.
>>> Brendan Eich wrote:
>>>> The new equivalence under private names would be x[#.id] === x.id.
> You said "under private names" here, but it should actually be
> "under the syntax proposed for private names".
Didn't I propose separating "private x" syntax two messages ago (but after I wrote the cited bit you snip here), and repeat that request last message? Argh.
> It applies to that
> syntax with either the soft fields or private names semantics.
No. #.id does not apply to soft fields.
>>> ... which is strictly weaker, more complex, and less explanatory.
>> So is a transposed get from an inherited soft field. Soft fields change the
>> way square brackets work in JS, for Pete's sake!
> They do not.
Ok, then I'm arguing with someone else on that point. But I still believe apples-to-apples comparison means mapping the same syntax to the two different semantics.
If the "private x" syntax, without #.id, is supported on soft fields, there's still a change to evaluating identifiers on the right of dot and the left of colon-in-object-initialisers, which has some complexity cost. This particular lexical binding and lookup cost doesn't change whether you use soft field side tables or private-named object properties for the value storage. At the very bottom of your reply, you return to this point (cited below).
>>> So, what if we want to understand '_._' in terms of existing constructs?
>>> Unfortunately, '#.id' must be primitive; there is nothing else that it
>>> can desugar to because 'private id' does not introduce an ordinary
>>> variable (unlike 'const id_ = SoftField()', say).
>> SoftField(), #.id -- something new in either case.
> Oh, OK, it obviously doesn't matter what we add to the language, it's
> all the same. Library abstractions, new syntax, major changes in
> semantics, who cares? Something new is something new. Let's just roll
> a bunch of dice and pick proposals at random.
This is sad. You can do better, read what I wrote, model it fairly and respond directly.
> Sheesh. A library class, specified in terms of existing language constructs,
> is not the same as a new primitive construct, and does not have the same
> consequences for language complexity.
No, we still disagree. "Executable specifications" have complexity and bugs. Weak maps (however harmonious) are complex too. Users who understand properties and objects do not generally know about "ephemeron tables". It still seems to me (and others who've sounded off) that you are discounting some complexity as a starting point for your favored approach, and ignoring the further complexity inherent in building library code as spec.
>> And what's this "const id_"? A gensym?
> A possible convention for naming variables holding private names.
Ok. That wasn't clear.
> It doesn't matter, you're picking on details.
I'm trying to understand what you wrote!
We are all detail-oriented here, no need to take offense all of a sudden. You yourself always wield a fine-toothed comb on details ;-).
>> It's tiresome to argue by special pleading that one extension or
>> transformation (including generated symbols) is "more complex, and less
>> explanatory", while another is less so, when the judgment is completely
>> subjective. And the absolutism about how it's *always* better in every
>> instance to use strong encapsulation is, well, absolutist (i.e., wrong).
> I gave clear technical arguments in that post. If you want to disagree with
> them, disagree with specific arguments, rather than painting me as an
> absolutist. (I'm not.)
Here's a quote: "As you can probably tell, I'm not much impressed by this counterargument. It's a viewpoint that favours short-termism and code that works by accident, rather than code that reliably works by design."
How do you expect anyone to respond? By endorsing bugs or programming based on partial knowledge and incomplete understanding? Yet the real world doesn't leave us the option to be perfect very often. This is what I mean by absolutism.
Weak encapsulation is defensible. It's not inherently wrong in all settings. When prototyping, weak or even no encapsulation is often the right thing, but you have to be careful with prototypes that get pressed into products too quickly (I should know). JS is used to prototype all the time.
Ok, of course prototypers need not use any of these facilities. But (it shouldn't surprise you to hear) I think prototype builders would benefit from very convenient private field support of some kind. Dave said so in his reply to Mark recently. We've all been burned by JS's softness and late error reporting.
So rather than argue for strong encapsulation by setting up a straw man counterargument you then are not much impressed by, decrying short-termism, etc., I think it would be much more productive to try on others' hats and model their concerns, including for usable syntax.
Does this make sense? I'm really not looking for a very long reply, and I'm not trying for some rhetorical advantage. But boy, it sure seems like you are.
>> We should debate strong vs. weak encapsulation, for sure, and in the other
>> thread you started (thanks for that). But without absolutes based on
>> preferences or judgment calls about trade-offs and economics.
> Tell you what, I'll debate based on the things I think are important, and
> you debate based on the things you think are important. Agreed?
Debate takes two people agreeing on proposition and rules. I'm not sure we can debate profitably, but I'm giving it another try here.
> To be clear, it's not the syntax itself, but the parallel namespace
> introduced by 'private x' that I find problematic in terms of both
> specification complexity, and conceptual complexity for programmers.
We did strive to make this namespace static.
You pointed out in a separate reply that #.id can promote private names from this static parallel namespace into runtime, but not in any scoped (dynamic) fashion. Just a value reflection, usable in brackets. No parallel runtime lexical and after-dot/before-colon scope chains.
>> It adds something to solve a use-case not satisfied by the existing
>> language. There's (again) a trade-off, since with this new syntax, the
>> use-cases for private names become more usably expressible.
> It isn't at all clear that there aren't alternative syntaxes that would
> achieve the usability benefit while not being subject to the criticisms
> that have been made of the current syntax proposal. Lasse Reichstein posted
> some possibilities (_.#_ or _[#_]). The syntax design space has been barely
> explored in the discussion so far.
I agree we need to explore more. Allen posted recently arguing for alternatives, but not pot-shots or concern-trolling -- coherent, worked out alternatives.
I'm not keen on adding # as a sigil for private names, but this is mostly because such things are ugly, Perlish line noise. Under the "explicit is better than implicit" philosophy, and in particular the desire to eliminate even a static (compile-time only) parallel namespace, *maybe*.
Usability experiments are tricky. Too many confounders, too little time to explore all the paths. We might be able to take at most two or three of syntax strawmen and test them on users.
Better if we can find something that wins general acclamation and keeps it. Clearly, we're not there yet with "private x" and sigil-free this.x.
>>> The fact that the proposal is entangled with that syntax, so that it is
>>> difficult to see its semantic consequences separate from the syntax,
>>> cannot possibly be considered a feature of the proposal, at the meta
>>> level of the language design process.
>> Didn't I already agree that it's a good idea to separate "private x" from
>> the semantics, since we have a conflict over semantics?
> It's clear how to do that for the soft field semantics, which are defined
> as a library abstraction.
> How do the proponents of private names propose to do that? (This is a
> technical question, not a rhetorical one.)
Change ToString to ToPropertyName where needed, follow your nose. Allen did list multiple sections (you never responded on that point).
There is probably a more principled way to do it, but again: just because soft fields can be a library on weak maps does not make that approach globally simpler, compared to widening property names from string to be (string | private name).
We no doubt could spend a long time fighting over how to measure complexity and score the two approaches, but touching more places in the spec is only part of the cost of private names.
>> So let's do that (my plea to everyone, not just you). Let's separate
>> "private x" syntax, since I now know of a use-case courtesy Mark, and it's
>> a good one (a frozen AST being extended sparsely via soft fields) that
>> wants that "private x" and the sweet dot operator syntax, but on top of
>> soft fields not private property names that require unfrozen objects.
> I can't parse that sentence; please clarify.
See followups in the thread.
[snipping VM implementor stuff, we agree that we need VM implementors to speak up.]
> There is a separate discussion to be had about whether the form of
> executable specification MarkM has used (not to be confused with the
> semantics) is the best form to use for any final spec. Personally, I
> like this form of specification: I think it is clear, concise (which aids
> holding the full specification of a feature in short-term memory), easy
> to reason about relative to other approaches, useful for prototyping,
> and useful for testing.
> I don't mind at all that the correspondance with the implementation is
> less direct than it would be in a more operational style; implementors
> often need to handle less direct mappings than this, and I don't expect
> a language specification to be a literal description of how a language is
> implemented in general (excluding naive reference implementations).
Once again, you've argued about what you like, with subjective statements such as "I don't mind".
I'm not sure how to respond, except to reiterate that the practical downsides of the executable spec approach remain over-specification and a mismatch with the (secondary) user and (primary) implementor audiences of the spec.
>> With inherited soft fields, the ability to "extend" frozen objects with
>> private fields is an abstraction leak (and a feature, I agree).
> How is it an abstraction leak? The abstraction is designed to allow this;
> it's not an accident (I'm fairly sure, without mind-reading MarkM).
If I give you an object but I don't want you "adding" fields to it, what do I do? Freezing works with private names, but it does not with soft fields.
> With private names, the inability to "extend" frozen objects with private
> fields is a significant limitation.
Can you try taking a different point of view and exploring it, for a change? :-/
>> With inherited soft fields, the transposed get or set magic that changes
>> how square brackets work in JS is a leak on the inside of the abstraction.
> "that changes how square brackets work in JS" is out of place here; we are
> discussing issues that remain after separating syntax, to the extent
> possible. In the inherited soft field proposal by itself, the syntax is
> 'field.get(obj)' and there is no magic. That is the proposal that I favour,
> absent some better proposal for the syntax.
I must have been arguing with Mark. Any proposal where x[n] becomes n.get(x) not only leaks inside the abstraction, but outside -- you can't write x.n or x.m for any m. Only square-bracketed indexing would work.
But it's finally clear you aren't in favor of this bracket syntax, so please ignore.
>> If you don't like x[#.id] / x.id supplanting x["id"] / x.id, it seems to me
>> you have to count some similar demerits against this change.
> If we compare both proposals with the additional syntax, they are equally
> "magical"; the only difference is whether the magic is built-in or the result
> of a desugaring.
Agreed. Disagree on desugaring to weak maps, not counting weak map complexity, or costs in executable spec approach, globally winning.
>> The weak encapsulation design points are likewise "leaky" for private
>> names, where no such leaks arise with soft fields: reflection and proxies
>> can learn private names, they "leak" in the real ocap sense that secure
>> subsets will have to plug.
> As I said earlier, designers of secure subsets would prefer that this leak
> not exist in the first place, rather than having to plug it. Regardless of
> your statements above, this is not an absolutist position; the onus is on
> proponents of weak encapsulation to say why it is useful to have the leak
> (by technical argument, not just some vague philosophical position against
> strong encapsulation).
This whole paragraph, "onus" in particular, is absolutism on parade.
Programmers use no-encapsulation and weak encapsulation in JS every day. On a purely "sociology of programming languages" or pedagogical level, you're selling some powerful hopium if you think this will change overnight to strong encapsulation by default. And hey, there's Alex Russell worrying about Mr. Freeze.
To be fair, I think that trends and tendencies do matter. The language is being used at larger scale, where integrity and other properties need automated enforcement (at the programmer's discretion).
But there's no onus reversal or technical standard of proof that will help us make design decisions. I know you want strong encapsulation. Others want weak. Now what?
[snipping stuff where we agree -- which was nice, btw!]
> Right. The syntactic and semantic proposals for soft fields are *already*
> separated; it is only private names proposal that does not separate syntax
> and semantics. It would be helpful to fix that, although I'm not sure it
> is possible to completely separate the syntax and semantics of the parallel
> namespace for private names.
To compare apples to apples, we'd want to do that. I don't see why we couldn't, with enough effort. Not tonight, though.
More information about the es-discuss