-
Notifications
You must be signed in to change notification settings - Fork 1
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
in which scope should the argument to inherit and use clauses be evaluated? #68
Comments
I think that they have to be evaluated in the surrounding scope. They clearly can't, for example, request methods on self, since neither self not its methods exist at the time the inherits and uses statements are evaluated. It would make sense to locate these clauses outside the braces that demarcate the object's scope, except that in a module, there are no braces and there is no outside. Regardless of what syntax we adopt for a manifest constant, such a constant also will beed to be evaluate in the surrounding scope. Unfortunately, this gets very complicated very quickly. Do we allow the keyword self to appear in an inherits statement? If so, does it mean the current object (which would be an error), or the surrounding object, which would be ok, but surely confusing. If we don't allow self, what is the right way to refer to the outer object? outer? But if we say that inherits is evaluated in the surrounding scope, then shouldn't outer mean the outer's outer? This is really horrible. |
I suggest no restrictions, but a strong warning (in the reference manual and perhaps a warning message emitted by the compiler) that it is evaluated in the outer scope. Only an idiot programmer would use self in the inherits, but, hey, we let idiots do all sorts of strange things. I think our notion of nested classes/objects leads to some complexities that other languages avoid, but most will use them with care (I hope!) |
well perhaps we should move them out.
Modules are already special. You can only have imports at the top level. We could allow inherits/uses clauses inside modules without breaking everything. Arguably the names introduce by "import" needs to go into an additional scope sandwiched between the dialect and the main module scope. We could run module inherits clauses in that scope too. |
If so, we should put that in the spec! The idea that modules are just objects, but objects that are named by a extra-language mechanism, was one of the great insights of Grace's design. Let's not spoil it by making too many differences between modules and other objects. Saying that imports must be at the top-level is OK. Changing the syntax is not. |
why not? #61 I think there is an argument that *inconsistent syntax between modules & object constructors is problem --- but as above I argue they are already inconsistent because the object { } is omitted for modules. That said: I can see an argument that modules could be "the body of an object { } constructor, prepended with import statements" --- arguing in favour of keeping the inheritance/uses clauses inside that body. On the other hand, if the arguments to those statements are executed in the surrounding scope, that breaks another principle, that "things are executed where they appear". So we have to choose. |
Rather than saying that inherits is executed in the surrounding scope, we could say that the inherited value cannot refer to anything declared in the current scope. This is subtly different! For example, rather than changing the meaning of self, it says that we can't utter self, and that outer in an inherits statement means the immediately enclosing object, as one would expect, and not the second-outermost enclosing object. |
(dunno why I can't see this on github (yet?)
we do:
manifest currently also stops implicit self. I added some consequent discussion to #67 cheers James |
Maybe I’m confused here, but I don’t see why parameters (either regular or type) to a class used in an inherits clause have to be manifest. If I define: class sup(arg1,arg2) { def x = o.m(73) // o may itself have been passed in from elsewhere class sub(rg) { then sup is certainly manifest in the inherits clause, but rg is not. Similarly, the value of x is certainly not manifest, yet can be used in the inherits clause. [My earlier suggestion of anything from the outer scope being OK wasn’t quite right either, because rg isn’t technically in the outer scope, but hopefully you know what I meant.] I’m also not certain why you would want type parameters to be manifest either. If I am defining a list of T, it’s not uncommon to want to define a subclass with some extra features (e.g., a length method). You want to keep this as a parameter that can be matched with the one from the superclass.
|
Can we talk about that at #47 |
#58 contains some nasty examples of using self in use or trait clauses.
Should we just say these expressions are evaluated in the surrounding scope?
The text was updated successfully, but these errors were encountered: