-
Notifications
You must be signed in to change notification settings - Fork 214
Class modifier spec disallows useful variants #2882
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
Comments
The
should be removed. It made more sense when we allowed you to mix in non- It's usually not a big issue to disallow that particular combination, because you can just define a pure So, "use It's just not a particularly good argument for disallowing I think we should just allow all combinations. Having an exception that disallows The restriction makes you can use the shorter @dart-lang/language-team |
Agreed. |
I agree that allowing all combinations is preferable to what I proposed due to the current migration cost. I believe this would eliminate the migration cost. I think greater readability can be achieved at the cost of initial discoverability. |
A very core part of the design of the original proposal was that the modifiers can be read positively. I continue to think it is a mistake to break this. Allowing things like |
I think this is a valuable observation. With this in mind, I would like to make a more radical proposal:
This would mean all My arguments for keeping
This would leave the following:
The lack of implict mixin constructor doesn't mirror how a There are probably different ways this can actually be implemented to achieve this syntax. |
We get pretty consistent feedback that users like having as few ways to say the same thing as possible. Why let them make a choice when the choice is pointless? It just leads to meaningless inconsistency?
That's fair. But it's not strictly required for us to support all possible combinations of capabilities. It's a goal, but I think we can afford to make some concessions and rule out particularly rare or confusing combinations if it leads to a more usable overall system. Most other languages don't have mixins or implicit interfaces at all and we're arguing over whether a user should be able to define a single type can be used as any arbitrary combination of them.
I had to read this several times before I realized that
|
It's not pointless. Lack of orthogonality is a cost. Every exception we make is one we need to explain, and which users need to remember and/or understand. I can't remember the reasons to not allow If we say that If we just allow it, we just need to tell them what I think the main usability issue here is if DartDoc shows Separate the useful capabilities from the source declaration in documentation, only show the capabilities that are actually relevant to outside users. |
The argument I have made, consistently, from the start, is that something which says
This is not true, precisely for the reason that I describe above. In order to understand what
I really don't understand this logic. If you believe that |
I've made this argument repeatedly, and in many different forums, but let me reiterate it here, one more time, for completeness, since it doesn't seem to have stuck. For context: the original proposal from @munificent from this past fall was interesting, but I found it very hard to reason about, because relied on negative capabilities. That is, you couldn't avoid talking about modifiers as "removing" capabilities, instead of adding them. This uniformly caused confusion. It confused @munificent and I when talking about it between ourselves, and with other people. Every time we combined two modifiers, we had to reason out what the combination meant. It was confusing. I made a counter-proposal based entirely on positive modifiers, and @munificent adapted some of those ideas to create what eventually became the proposal that we accepted. The essential key point of that design that made it acceptable was that it did not require reasoning about negative capabilities, and that the modifier on a declaration tells you directly what you can do with it. Specifically: If you have a declaration which says
If you have a declaration which says
Now, it is also true that there implied negative parts to this. An It is also true that the implied negative parts above don't apply inside of a library. And that's also.. ok! As an external user of the code, you don't really need to know what happens in the privacy of the library. Now if we add
Now it is true that you can also use that class for other things. And this is an irregularity. If you have an As soon as you start combining other modifiers with All of this is deeply confusing, and provides essentially no value to users. Do we have any actual examples that require this (and that can't easily be restructured)? I don't have any. I certainly think that orthogonality is a nice design principle, but I don't think this is a reasonable place to apply it. If we really believe that orthogonality is an overarching need here, I would prefer that we move to something like what I originally proposed, in which capabilities were entirely orthogonal positive capabilities that can be combined arbitrarily. But on balance, I personally think the existing design is better. Less orthogonal, yes, but it cleanly captures the important use cases in a way that is both concise and understandable. |
You have a point, but it's a point which is applied inconsistently, and looking at my own way of thinking, that's mainly because of familiarity with existing forms, but no familiarity with The argument that A A
And we're back to me not reading And it gives us a fairly simple and consistent story we can teach users:
If we start treating
You can use this mixin as a mixin, if it's marked
No, but it works exactly like an Nobody has seen these modifiers in Dart before. We get to teach people how to read them. How to write declarations:
How to read declarations (from outside the library), and see what you can do with it:
Or more goal oriented:
Introducing
So let's just not do that! |
We wouldn't need |
Are they distinguishable in that they allow expressing different capabilities for the users of a library, or only distinguishable in that the author of a library might need a workaround like an extra private class or mixin? |
Sure, let me talk a bit about more why I don't find this to be a good argument. TL;DR - a design which requires users to correctly resolve a syntactic ambiguity in order to arrive at the right semantics is a bad design. Let's start by talking about large horned mammals and energy drinks. The phrase "red bull", depending on your priors and on context, might refer the former (which happens to be colored red), or it might refer to a popular energy drink. The former case arises by parsing the phrase as a modifier applied to a noun (red (bull)). The latter case arises by parsing the phrase as a compound noun phrase (red bull). There is a meaningful syntactic ambiguity here: the same piece of syntax can be parsed in two different ways, and depending on the parse, you will end up with one of two different semantic objects. There is an ambiguity and it is significant. There are two observations I would draw from this. Firstly, unless a writer is confident that their readers know that "red bull" is a compound noun, and that they are using it as such, they risk greatly confusing their readers by using it. That is, compound nouns are error prone to start with if they are not self-explanatory. If the writer starts talking about a "colorless red bull", then unless the reader knows that "red bull" means "brand of energy drink" (which may or may not be red), then the reader is likely to be highly confused and think that they are reading jabberwocky. If "sour red bull" is green, then a reader who parses "red bull" incorrectly will be very surprised to learn that a (sour (red (bull)) is green, because modifiers compose, while compound nouns which include modifying words do not (necessarily) do so. Secondly, regardless of whether a reader can be expected to know of the existence of both (red (bull)) and (red bull), it is bad writing to use the phrase in a context where the two can be confused. That is, writing a paragraph in which the phrase "big bull" (meaning "large mammal") and "red bull" (meaning "energy drink") both occur in conjunction is almost certainly confusing and, is bad writing. So now let's talk about "mixin class". In the existing proposal, it is irrelevant whether "mixin class" is a modified noun (mixin (class)), or a compound noun (mixin class). This is a good thing. There is a syntactic ambiguity, but it doesn't matter how it is resolved. We end up in the same place. This is especially good, because we are not trying to claim that "interface class" et al are compound nouns. So a user who very naturally parses "mixin class" the same way we expect them to parse "interface class" will, nonetheless, end up with the correct semantics. Once you allow things like "interface mixin class" however, this goes out the window because modifiers compose, but compound nouns do not. That is, just as a (sour (red (bull))) is necessarily red but a (sour (red bull)) is not, an (interface (mixin (class))) is necessarily usable as a mixin but an (interface (mixin class)) is not. There is a syntactic ambiguity, and unless you know how to resolve that syntactic ambiguity somehow, you will naturally arrive at an incorrect semantic interpretation. In general, I think the entire project of trying to treat "mixin class" as a compound noun is highly suspect in the context of a programming language. We just don't do that very much, and I think for good reasons. It's hard to users to parse - modifiers are very standard and compound nouns are not - and if the difference matters, they will naturally be led astray. And relying on educating users about your intended interpretation is, I think, not realistic. Most people learn code by reading it. They will have seen "interface class" and learned what it does by example, and they will have seen "mixin class" and learned what it does by example, and then they will see "interface mixin class" and they will be deceived. So my takeaway is that by all means, think of "mixin class" as a compound noun if you wish, but I am adamantly opposed to requiring our users to do likewise. Concretely to some of your points.
Firstly, it is not confusing because
A
That story is anything but simple and consistent. I was lost by the third bullet.
Users will parse it that way. I'm sorry. They will. Go out on the street, ask the first random 10 programmers you meet what they think "red blue class" means, and I will give you $100 for everyone that says "Ah,
No we don't. They will teach themselves. And having APIs scattered around that say "interface mixin class Foo" on things which don't allow use as a mixin, will teach them via repeated, painful, stubbing of toes.
We are, on this, at last, 100% agreed! |
So, how about using Thanks @natebosch. And about:
I don't think there is anything you can do with an Same for For the remaining cases: That is: The only three pairs of declarations (using
The rest are distinguishable in expressive power in at least one way, either externally or internally. If we apply the same logic (if you can mixin, you don't need to be able to extend) to public API, then The reason we (at least I) wanted |
Maybe |
I think the original issue/bug was addressed and resolved, so I'll close this to clear the way for new issues which might argue in favour of a particular disallowed modifier. |
Uh oh!
There was an error while loading. Please reload this page.
https://github.com/dart-lang/language/blob/master/accepted/future-releases/class-modifiers/feature-specification.md
The feature spec seems to use the following statement as justification to disallow the declaration variant
sealed mixin class
:I don't think this is a good reason to disallow variants.
Unless I'm misunderstanding, the justification seems to be used to disallow two other constructable variants-
interface mixin class
andfinal mixin class
:Instead, I think dart should disallow any declaration variant that solitarily adds to a shorter declaration variant the in-library capability of
extend
where mixing in is allowed. This doesn't apply tofinal mixin class
orinterface mixin class
.The variants the proposed justification would disallow are:
sealed mixin class
(should instead besealed mixin
)abstract interface mixin class
(should instead beinterface mixin
)abstract final mixin class
(should instead befinal mixin
)interface mixin class
andfinal mixin class
would be allowed.The text was updated successfully, but these errors were encountered: