-
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
methods of graceObject #155
Comments
So, the thing is, once you've got rid of everything in
How does it do that? Seems to me saying that print does not depend on
right - and the complexity costs different choices impose on the rest of the language. Printing/stringification, I think, we can handle in various ways. Equality seems more important to me. Ideally we would look through @KimBruce's book (or other curricula) to answer questions like:
|
None could be defined by magic. It could even (almost) be |
I tried looking through Kim's book - as far as I can see, == etc are only used on primitives or library objects, HMM: turns out we've been over this already. #49 (comment) seems like Kim would prefer ==, != and friends in all objects, but is happy with a trait to include them. I think the simplification of inheritance is worth it. |
Yes, we did discuss this already, when I removed What I propose it try in SmallGrace is as follows:
A related point is that |
answered back at #32 (comment) |
yeah I think so. now, anyway. |
we adopt the small grace design |
You can see what's in SmallGrace in the github repo. Right now, the trait that implements identity equality is called
It describes objects with either of the equality traits. |
Here are the changes that I propose making to the spec. If you want to see them nicely formatted and in color, view them on github Otherwise, here is the diff;
|
Seems reasonable to me.
Kim
… On Sep 12, 2018, at 10:25 PM, Andrew Black ***@***.***> wrote:
Here are the changes that I propose making to the spec. If you want to see them nicely formatted and in color, view them on github <master...equalityChanges>
Otherwise, here is the diff; + is an addition, and - is a deletion.
@@ -1216,17 +1216,36 @@ default methods.
| Method | Return value |
| :----------------------------------------------- | :------------------------------------------- |
| `isMe (other:Object) → Boolean`; _confidential_ | true if other is the same object as self |
-| $\neq$ `(other:Object) → Boolean`| the inverse of == |
+| `myIdentityHash → Number`; _confidential_ | a hash code characteristic of this object |
| `asString → String` | a string describing self |
| `asDebugString → String` | a string describing the internals of self |
-| `:: (other:Object) → Binding` | a Binding object with `self` as key and `other` as value|
-Notice that `graceObject` implements $\neq$ but not `==`.
-This is to help ensure that, when an object chooses to implement `==`,
-$\neq$ is also available, and is the inverse of `==`.
-If desired, the _confidential_ method `isMe` can be used in the implementation of a
-public `==` method.
+Notice that `graceObject` implements neither `==` nor `≠`.
+In the _standardGrace_ dialect, the trait `equality` is available to help
+in their implementation.
+
+
+ trait equality {
+ method == (other) is required
+ method hash is required // should obey invariant (a == b) => (a.hash == b.hash).
+ method ≠ (other) { (self == other).not }
+ method :: (obj) { binding.key (self) value (obj) }
+ }
+
+As the `is required` indicates, an object using this trait must provide an `==` method,
+and a corresponding `hash` method.
+One way to define these methods is by combining the equality and hash on the
+results of all the observer methods;
+another is to use `identityEquality`, which defines `==` as object identity and `hash` as
+identity hash.
+
+
+ trait identityEquality {
+ use equality
+ method == (other) { self.isMe(other) }
+ method hash { self.myIdentityHash }
+ }
# Method Requests
@@ -1819,21 +1838,27 @@ Type `None` is completely empty; it has no methods.
### Type Object
-The type `Object` includes methods to which most
-objects respond --- the [Default Methods] declared in
-`graceObject`. Some objects, notably `done`, do not conform to `Object`.
-
+In _standardGrace_, type `Object` includes just the public [Default Methods] declared in
+`graceObject`.
- type Object = {
- != (other: Object) -> Boolean // the inverse of ==
+ type Object = interface {
asString -> String // a string for use by the client
asDebugString -> String // a string for use by the implementor
- :: (other:Object) -> Binding // a binding with self as the key
}
-Notice that `isMe`, although present in [`graceObject`](#default-methods), is not present in
-type `Object`, because it is *confidential*.
-Also notice that neither `graceObject` nor type `Object` include `==`.
+Notice that `isMe`, and `myIdentityHash`. although present in [`graceObject`](#default-methods),
+are not present in type `Object`, because they are *confidential*.
+
+### Type EqualityObject
+
+In _standardGrace_, type `EqualityObject` adds the family of equality methods to `Object`:
+
+ type EqualityObject = Object & interface {
+ ::(o:Object) -> Binding
+ ==(other:Object) -> Boolean
+ ≠(other:Object) -> Boolean
+ hash -> Number
+ }
### Type Self
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub <#155 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/ABuh-uCri360NN6ctwNsp37_1F6m35LGks5uaew6gaJpZM4R5LOB>.
|
In the spec it says that any object not inheriting from anything else inherits from graceObject, and that graceObject defines the following methods:
isMe (other:Object) → Boolean
; confidential(other:Object) → Boolean
asString → String
asDebugString → String
:: (other:Object) → Binding
self
as key andother
as valueThe method
≠
was put there (by me) as a placeholder, until I had implemented traits; once we have a traitidentityEquaility
defined by something likethere is no reason to put
≠
ingraceObject
.I've also realized that, since
==
is no longer ingraceObject
,::
should not be ingraceObject
either: if you can't test an object for equality, you can't use it as a key in a dictionary, which is the motivation for::
. So we should move::
to traitsidentityEquaility
andabstractEquality
(the latter being a trait that requires the user to define==
andhash
and provides≠
and::
).Much as I really liked the conclusion in The Left hand of Equals essay — that we should have a confidential
isMe
method in every object, which the object can choose to expose if it so wishes — we don't really needisMe
either. This is because we also admitted in that essay that we needed an identity-testing method inmirror
, and once we have that, theidentityEquality
trait can defineand the user of the
identityEquality
trait won't see any difference.This leaves
graceObject
with just the two stringification methodsasString
andasDebugString
. In practice, I really like having those methods be available by default, and I've taken some pains in minigrace to try to make the default implementations be useful. So, for example,prints "a horrible", not "an object".
But the fact remains that the type
Object
is now the same as the typeDone
, which doesn't feel right.Object
andDone
still have different pragmatics: one is intended to be the supertype of all other types, while the other is intended to be the return type of an operation (such as an assignment) that has no result. Our type system doesn't reflect this difference, though.To some extent we can sidestep this issue by saying that
graceObject
(the superobject off all objects) is defined by the current dialect, and thus is not part of the core language, whereasDone
is defined by the core language, because it characterizes the object returned by an assignment (which I think has to be defined in core Grace). If we do that, though, we need a way of defininggraceObject
in a dialect that does not requiregraceObject
to be already defined. I've thought of usingfor this, but then we have to ask: where is
none
defined? And so on.@kjx has argued that we should be "pure" and get rid of
graceObject
altogether, so that type Object would be empty and there would be no default inheritance. I've argued against that because of the enormous practical advantages of having every object supportasString
andasDebugString
.Like most issues in OO, the real concern here is not whether we have default code to stringify any object — we need that regardless, because user-written asDebugString methods can fail — but where to put it.
The text was updated successfully, but these errors were encountered: