Is there a reason we can't have "deriving (eq, ord)" for interfaces? #168
Replies: 4 comments 40 replies
-
For better understanding, can I summarize it like that? Equality is sometimes context-specific. If it is, my reasoning would be: |
Beta Was this translation helpful? Give feedback.
-
I appreciate the notes @artwyman! I believe we're already using the modularization part of Djinni -- we have over a dozen .djinni files and some of them depend on types from other .djinni files. I had a bit more trouble following the hand-rolled translator part though if that's what you were suggesting I use. I'll look at that more closely on Monday. And I should say that I used 'deriving' as an example of the kind of notation to use, your description of how it should actually work is pretty much exactly what I was suggesting: generate the equality stubs and the developer fills them in with the behaviour they want. In practice, it wouldn't be And a wrapper can be used -- at least in Java -- to workaround this for things like HashMap -- mostly. It's a bit cumbersome and annoying, but it would work. My colleague whipped out a quick generic that would do the trick, but that won't help with Djinni itself. When I return a @a4z The system in question is actually one I started building about a month ago and I alluded to the only way to avoid this problem -- namely keeping the djinni objects I create for methods in the object that spawns them. That can obviously be a good thing, but in a multi-threaded environment like ours, there could very well be two copies of a Layer object floating about and keeping them in synch is going to be a nightmare. The Djinni objects are, in the end, vessels for the underlying data so while I could design it (or even pivot now since its not in production) I think the solution to the equality problem creates a much harder synchronization problem. And in the end, it just feels like being able to define equality would be a good thing. All the languages Djinni supports (that I know, which is most) support the idea so why not have it as feature? Clearly lots can be done without it given the number of users, but I think it would make the the generated objects more powerful to have the feature. At any rate, the main purpose of this thread was to make sure there wasn't either some major technical hurdle I didn't know about that would preclude it, or if it would be a feature that would be unwelcome. It doesn't sound like either of those things is true so I'm happy to take a stab at it when I have time (which could be a month or two). Even if it's not ultimately accepted, at least I know I wouldn't be wasting my time in the attempt! I really appreciate the robust & rapid feedback! |
Beta Was this translation helpful? Give feedback.
-
OK, so I had some time earlier than I thought I would and I couldn't let this go so I went ahead and I've managed a rough implementation. PR is #169. I've tested it with my own code and using this I was able to drop that val firstAttribute1 = layer.attributes.first()
val firstAttribute2 = layer.attributes.first()
assertEquals(firstAttribute1, firstAttribute2)
val map = hashMapOf(
firstAttribute1 to 1,
firstAttribute2 to 2
)
assertEquals(1, map.size) When you get a chance, please take a look. I still don't know scala very well, but I was able to cobble this together by looking at the existing code since in many ways I'm not actually writing new logic, just new versions of existing logic. I'm sure it can be done more elegantly than I've done here so I would be happy to take suggestions on style or approach in addition to whatever other criticisms you can offer! Thanks! |
Beta Was this translation helpful? Give feedback.
-
Sorry for the silence for a week, but I finally have some more time to put into this. Publishing C++ to Java (and I think Obj-C) seems to be satisfactory at the moment (pending unit tests) so I was mulling publishing Java to C++. First, I wasn't sure if this was a requirement or not of the feature. If it isn't possible or if it feels too awkward, is that the end of it or is it okay for To make +j work with namespace std {
template<>
class hash<shared_ptr<ClassName>> {
public:
size_t operator()(const shared_ptr<ClassName>& a) const
{
// invoke Java object's hashCode() method via JNI
}
};
}
// does not help with std::map but is needed with above hash for unordered_map
bool operator==(const std::shared_ptr<ClassName>& left, const std::shared_ptr<ClassName>& right)
{
return left && right && // call ClassName.equals() through JNI
} This obviously comes with some baggage, but maybe because it's opt-in, that's fine. Ordering would be similar: // this is sufficient to make the map look at IDs
bool operator<(const std::shared_ptr<ClassName>& left, const std::shared_ptr<ClassName>& right)
{
return left && right && // call ClassName.compare() through JNI and return true if < 0
} I wrote up some Godbolt test cases to make sure this would work, and it does. Not sure if this is too ugly to use though. I'm pretty sure there's no other way to do it though. You can see my rough work here: https://godbolt.org/z/d765zbMax As always, thoughts appreciated! If we don't need to publish Java or Obj-C to C++ for the feature to be approved, I'll just move on to unit tests and circle back to this later if we're interested. If it is required, I can fiddle with an implementation of the above if that's deemed satisfactory. |
Beta Was this translation helpful? Give feedback.
-
We use djinni quite a bit (big thanks!) but one frustration I keep running into is the inability to easily compare two objects of the same type on my terms. Since my djinni objects are almost always wrappers around lower level C++ objects I'd love to be able to have to djinni objects in Java compare using a method defined by my C++ objects.
For example, I have a djinni object representing an object that has an ID. I don't want to share that ID with the Java code, but it is there under the hood. When I compare to of these objects I assume Java is looking at the references and deciding they're not equal even though their IDs are -- being able to implement
equals()
andhashCode()
in C++ would solve this.The
deriving ()
operators specifier for Record works really well. It feels like it could do the same thing for interfaces, but instead of generating all the code, why couldn't it just call abstract methods like it does with any any other generated method? I can see how it would work pretty easily with Java, so maybe the problem is other languages?Beta Was this translation helpful? Give feedback.
All reactions