Closed kjx closed 6 years ago
Let's be clear, we don't really need this as a language feature.
Object level exclude x
can always be written method x is confidential required
.
Object level alias n = m
can nearly always be written method n { m }
, and where that doesn't work (e.g., to protect against subsequently overriding of m
) can be sorted with more aliases on inheritance clauses, or renaming m
as something horrible like myFoo_m
, writing method m { myFoo_m }
and being careful never to override myFoo_m
. If we had a final
annotation on methods, you'd make myFoo_m
final.
Let's be clear, we don't really need this as a language feature.
Wasn't one of our original goals (design principles, whatever) to keep Grace as simple as possible?
I can see the motivation for the alias
clause in an object, but one can get the same effect by defining a block in the object constructor, and then having two methods that both apply that block. This is proof against the overriding of one or the other method.
As for allowing exclude x
in an object that does not define x
: that seems daft. In fact, we already say that excluding x
when x
is not present is an object composition error.
You do bring up one good point, though: the spec also says that excluded attributes are replaced by a confidential, required method. This seems wrong to me; if one wanted a confidential, required method, one could define one, which would override the reused attribute, and there would be no need for exclude. I think that we need exclude exactly when the attribute being excluded is not required. Of course, I don't yet have much experience with exclude, so my view on this may change.
Wasn't one of our original goals (design principles, whatever) to keep Grace as simple as possible?
absolutely! That's certainly my motivation e.g. behind reconsidering self and outer requests #140
I can see the motivation for the alias clause in an object,
actually my main motivation was to have a lexical "parallel" of alias...
As for allowing exclude x in an object that does not define x: that seems daft. In fact, we already say that excluding x when x is not present is an object composition error.
Yep. On reflection it probably wouldn't work the way I want it to - if i define a required/abstract method in an object, doesn't that definition override all inherited definitions (even if there is a non-abstract inherited definition). Hmm: the spec says it does. This is why I'm trying to come up with some kind of simple formal/operation definition of what these things do - so we have something concrete to argue about.
The problem with the current local-required-overrides-everything semantics are that I cannot then write a declaration to ensure (or at least hint) a receiverless request will be resolved via inheritance in a concrete object. I can do it on the use side (by requesting self.x
, assuming we either don't have the Eiffel rule, or x
is public); I can do it in a a trait or abstract class by declaring a required method but I can't see a way to say "I expect all requests of x to be resolved via inheritance, not lexically" - and either make it so, irrespective of lexical declarations, or at least ensure an ambiguity error is raised.
In the following, we expect encl2.sub.test
to always resolve to "encl.x", right?
incl
can indicate it wants to resolve x
via inheritance by declaring an abstract method.
I can't see way for sub
to say "resolve x to a (future overriding) subclass definition, or
failing that an inherited declaration from any parent".
def encl = object {
method x { print "encl.x" }
class incl {
method test { x }
}
}
def encl2 = object {
method x { print "encl2.x" }
class sub {
inherit encl.incl
method x { print "sub.x" }
}
}
sub.test
OK, on more reflection, could sub do:
class sub {
inherit encl.incl
alias super_x = x
method x { super_x }
}
would that do what I want?
You do bring up one good point, though: the spec also says that excluded attributes are replaced by a confidential, required method.
Isn't the declaration coming down from the inherited/used "super-part-object" replaced, not the local declaration in the inheriting/using object?
I remain concerned that the "tentative" multi-stage reuse semantics are not "as simple as possible".
would that do what I want?
I don't really know what you want, or the point of this "issue". If it really is a low priority placeholder for you, maybe I should just ignore it?
I don't really know what you want, or the point of this "issue".
What I want is mostly from #140 - are alias and exclude (on inheritance) and other coding workarounds (on enclosing lexical scopes) enough that we can do without special self and outer requests?
(We'd still have self
and outer
but as pseudo-defs, not as request types --- you wouldn't lose anything by putting them in another def and then doing the request on that def).
If it really is a low priority placeholder for you, maybe I should just ignore it?
sure.
another example of "kjx's useless, distracting, and pointless F**king around" as we put it in the discussion this morning
We could allow
alias
andexclude
in objects (and classes). Consider:This would give the object a method
n
with the same logical body asm
, and aconfidential
,required
methodx
.I'm not actually keen on this as a design - although what's odd is that writing
exclude x
is pretty close to writingmethod x required
(or whatever the final syntax is).Alias clauses in objects would allow ambiguous outer requests to be disambiguated on the declaration side (rather than the call side). E.g. something like
note that
out.in.test
will result in an ambiguous internal request ofm
.The example can be rewritten (only changing local lexical scope) to something like this:
where programmers can now get around the ambiguity (but without using special
self
orouter
requests). If programmers really want the inner object to have anm
method they could add in either(or almost equivalently)
to go up inheritance, or
to go out lexically. We could even twist alias to allow
alias m = out_m
in this case, but that's probably one step to far.