Closed kjx closed 8 years ago
I'm glad you picked up on this. Having exclude actually delete (as opposed to hide) stuff breaks huge numbers of things. Your other examples (issue 71?) show this is even worse by having a reference to an a in a superclass that is excluded in a super class, end up referring to a completely different a in the outer scope!
Remember when we wanted to keep the language simple!! I don't think alias is a big deal, and hide (rather than exclude -- i.e., make it no longer in scope) is doable (though it would be simpler not to have it).
Here is my vote for making it simpler. Keep alias, replace exclude with hide (or eliminate the construct all together), and treat aliases as local definitions in the module they are defined in. Yes, the last adds another feature, but these aliases are already static references (like super was). Keep it simple or we will blow up the whole language design and we will never get any buy in to this as an educational language!!
If you want, try more experimental versions in separate branches but now is not the right time to open those cans of worms, especially if we are trying to get others to use the language. As James says, all we really need is to be able to combine dialects. Everything else can be programmed around fairly easily.
Here is my vote for making it simpler. Keep alias, replace exclude with hide .... the last adds another feature...
which is why this "simple" stuff is rarely simpler. What's more complex: alias or aliasAndAbstract (aka aliasAndExclude) #73
Remember when we wanted to keep the language simple!!
yep - and I have a list of complicating things: overloading on arity, traits/multiple inheritance, precedence, etc, some of which we've added earlier, some later. I'm sure we all have our own favourite bits and pieces of complexity...
So, we've decided that "exclude" introduces a "required" method. Is that method confidential or public? I'm leaning toward having it be confidential. That way it disappears from the type, but is there for superclass calls (so we get a better error message if it is accidentally called).
Related to this is the question of how to write a trait when it's body depends on a missing method. E.g., if I write method m that depends on another method n, that is not included in the trait.
I personally would prefer to require that the trait include the method n as a "required" method. I suspect others won't agree, but thought I would put that out there just in case. For me it is a matter of documenting the dependencies of the trait.
So, we've decided that "exclude" introduces a "required" method. Is that method confidential or public?
good point. we really have to think about the crossproduct of every annotation, don't we? I believe we decided alias introduced a new confidential alias - that's what the spec says, so presumably exclude should do something similar.
Related to this is the question of how to write a trait when it's body depends on a missing method I personally would prefer to require that the trait include the method n as a "required" method.
It's clear that you can include a required method; it's pretty clear that you probably have to do so if you want to be able to type-check the trait independently. In some cases (if you have an enclosing lexical definition) you must put in a required method to ensure implicit requests resolve to the right place. The question is: whether you have to do it anyway.
Given other decisions we've made --- e.g. that the 'override' annotation is not required, and a general philosophy that errors should be generally be signalled as late as possible, it would seem odd to require those definitions.
I put that change into the spec..
Michael pointed out that replacing an exclude public
method with a confidential required
breaks the type of the parent.
If subtyping and subclassing are that different #82 , then local analyses of super-objects are "uninformative": the only analysis that actually counts is the analyses of each concrete object including all its parents (or not). E.g. if you override superclass methods, the fact that they have type errors no longer applies.
https://github.com/gracelang/language/issues/82#issuecomment-197045885
Yes, passing self as a parameter to something else from a method m of a superclass will break type-checking if that something else needs method p and method p was excluded in a subclass.
I will likely never use exclude and will bar it from statically typed dialects. I'd rather not have it in the language at all, but can live with it if others find compelling cases for it for their own work.
The rules for exclusion (in particular), perhaps aliasing, perhaps manifest, preclude modular type-checking of traits and classes. That is to say: we have to (re)check the code of all supertraits and superclasses in the context of all subclasses, and such checks may report errors in superclass code.
We can write and presumably type-check
subClass.b
but the class will fail because the subClass instance doesn't understanda
. There's no way to tell that just by looking at the definition ofsuperClass
.If we adopt the manifest through inheritance design #47, or/and emphasize flattening #71