July 12, 2012
Andrei Alexandrescu:

> Too complicated. I think we can afford one comparison.

An annotation for old style classes?

Bye,
bearophile
July 12, 2012
On Thursday, 12 July 2012 at 13:49:29 UTC, Andrei Alexandrescu wrote:
> Too complicated. I think we can afford one comparison.

One comparison for each of these basic usages. Would branch prediction work fine in each use case?

Anyway I vote for removing those methods from the root class.
July 12, 2012
On 12/07/2012 06:15, Andrei Alexandrescu wrote:
> Required reading prior to this: http://goo.gl/eXpuX
>
> You destroyed, we listened.
>
> I think Christophe makes a great point. We've been all thinking inside
> the box but we should question the very existence of the box. Once the
> necessity of opCmp, opEquals, toHash, toString is being debated, we get
> to some interesting points:
>
> 1. Polymorphic comparisons for objects has problems even without
> considering interaction with qualifiers. I wrote quite a few pages about
> that in TDPL, which add to a lore grown within the Java community.
>
> 2. C++ has very, very successfully avoided the necessity of planting
> polymorphic comparisons in base classes by use of templates. The issue
> is template code bloat. My impression from being in touch with the C++
> community for a long time is that virtually nobody even talks about code
> bloat anymore. For whatever combination of industry and market forces,
> it's just not an issue anymore.
>
> 3. opCmp, opEquals, and toHash are all needed primarily for one thing:
> built-in hashes. (There's also use of them in the moribund .sort
> method.) The thing is, the design of built-in hashes predates the
> existence of templates. There are reasons to move to generic-based
> hashes instead of today's runtime hashes (such as the phenomenal success
> of templated containers in C++), so it can be argued that opCmp,
> opEquals, and toHash exist for reasons that are going extinct.
>
> 4. Adding support for the likes of logical constness is possible, but
> gravitates between too lax and onerously complicated. Walter and I don't
> think the aggravation is justified.
>
> There are of course more angles and considerations. Walter and I
> discussed such for a while and concluded we should take the following
> route:
>
> 1. For the time being, rollback the changes. Kenji, could you please do
> the honors? There's no need to undo everything, only the key parts in
> object.d. Apologies for having to undo your work!
>
> 2. Investigate a robust migration path from the current use of opCmp,
> opEquals, toHash (we need to also investigate toString) to a world in
> which these methods don't exist in Object. In that world, associative
> arrays would probably be entirely generic. Ideally we should allow
> existing code to still work, while at the same time fostering a better
> style for new code.
>
>
> What say you?
>
> Andrei

I also had a tilt on that message. This is after reflexion definitively the way to go. metaprogramming rox.
July 12, 2012
Is this really need?

The four const operators in Object should not block the user-defined mutable operators.

// My purpose for 2.060 release
class C {
  override opEquals(const Object o) const { ... } // or just alias
super.opEquals opEquals;
  bool opEquals(Object o) { ... } // add overload for mutable object comparison
}

auto c1 = new C(), c2 = new C2();
c1 == c2;   // the both hand side is mutable, so mutable opEquals will run

In git head, it is not disallowed, but it is a *compiler bug*.
To fix the problem, I have a pull request for dmd.
https://github.com/D-Programming-Language/dmd/pull/1042
(The pull will kill attribute inference for const, but I think it is
unnecessary for D.)

...But, I would never opposed to advancing toward the better language design.

Kenji Hara

2012/7/12 Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>:
> Required reading prior to this: http://goo.gl/eXpuX
>
> You destroyed, we listened.
>
> I think Christophe makes a great point. We've been all thinking inside the box but we should question the very existence of the box. Once the necessity of opCmp, opEquals, toHash, toString is being debated, we get to some interesting points:
>
> 1. Polymorphic comparisons for objects has problems even without considering interaction with qualifiers. I wrote quite a few pages about that in TDPL, which add to a lore grown within the Java community.
>
> 2. C++ has very, very successfully avoided the necessity of planting polymorphic comparisons in base classes by use of templates. The issue is template code bloat. My impression from being in touch with the C++ community for a long time is that virtually nobody even talks about code bloat anymore. For whatever combination of industry and market forces, it's just not an issue anymore.
>
> 3. opCmp, opEquals, and toHash are all needed primarily for one thing: built-in hashes. (There's also use of them in the moribund .sort method.) The thing is, the design of built-in hashes predates the existence of templates. There are reasons to move to generic-based hashes instead of today's runtime hashes (such as the phenomenal success of templated containers in C++), so it can be argued that opCmp, opEquals, and toHash exist for reasons that are going extinct.
>
> 4. Adding support for the likes of logical constness is possible, but gravitates between too lax and onerously complicated. Walter and I don't think the aggravation is justified.
>
> There are of course more angles and considerations. Walter and I discussed such for a while and concluded we should take the following route:
>
> 1. For the time being, rollback the changes. Kenji, could you please do the honors? There's no need to undo everything, only the key parts in object.d. Apologies for having to undo your work!
>
> 2. Investigate a robust migration path from the current use of opCmp, opEquals, toHash (we need to also investigate toString) to a world in which these methods don't exist in Object. In that world, associative arrays would probably be entirely generic. Ideally we should allow existing code to still work, while at the same time fostering a better style for new code.
>
>
> What say you?
>
> Andrei
July 12, 2012
On 12/07/2012 11:51, Jonathan M Davis wrote:
> On Thursday, July 12, 2012 02:43:09 Walter Bright wrote:
>> On 7/12/2012 12:59 AM, Jonathan M Davis wrote:
>>> So, I think that it's probably a solid way to go, and it does appear to
>>> solve the const issues that we've been having quite nicely, but it also
>>> appears to break a number of things which have worked for some time, and
>>> we're going to have to figure out how we're going to deal with that, even
>>> if it's only providing a good deprecation path.
>>
>> A main motivation for going this route is to avoid breaking existing code.
>
> Except that it's _guaranteed_ to break code, because anything which relies on
> Object having opEquals, opCmp, toHash, or toString is going to break. We can
> provide an appropriate deprecation path to ease the transition, but this
> _will_ break code.
>
> - Jonathan M Davis

I'd advocate that rely on Object isn't a wise idea anyway. I've worked quite a lot in java and it is a recurring problem (mostly because of the way generic is implemented). The problem we encountered here are another confirmation of that.

We have much greater metaprogramming capabilities than Java, and it seems like a good idea to leverage that.
July 12, 2012
On Thursday, 12 July 2012 at 11:03:37 UTC, Don Clugston wrote:
> On 12/07/12 12:00, Paulo Pinto wrote:
>> On Thursday, 12 July 2012 at 08:59:46 UTC, Don Clugston wrote:
>>> On 12/07/12 06:15, Andrei Alexandrescu wrote:
>>>> Required reading prior to this: http://goo.gl/eXpuX
>>>>
>>>> You destroyed, we listened.
>>>>
>>>> I think Christophe makes a great point. We've been all thinking inside
>>>> the box but we should question the very existence of the box. Once the
>>>> necessity of opCmp, opEquals, toHash, toString is being debated, we get
>>>> to some interesting points:
>>>>
>>>> 1. Polymorphic comparisons for objects has problems even without
>>>> considering interaction with qualifiers. I wrote quite a few pages about
>>>> that in TDPL, which add to a lore grown within the Java community.
>>>>
>>>> 2. C++ has very, very successfully avoided the necessity of planting
>>>> polymorphic comparisons in base classes by use of templates. The issue
>>>> is template code bloat. My impression from being in touch with the C++
>>>> community for a long time is that virtually nobody even talks about code
>>>> bloat anymore. For whatever combination of industry and market forces,
>>>> it's just not an issue anymore.
>>>>
>>>> 3. opCmp, opEquals, and toHash are all needed primarily for one thing:
>>>> built-in hashes. (There's also use of them in the moribund .sort
>>>> method.) The thing is, the design of built-in hashes predates the
>>>> existence of templates. There are reasons to move to generic-based
>>>> hashes instead of today's runtime hashes (such as the phenomenal success
>>>> of templated containers in C++), so it can be argued that opCmp,
>>>> opEquals, and toHash exist for reasons that are going extinct.
>>>>
>>>> 4. Adding support for the likes of logical constness is possible, but
>>>> gravitates between too lax and onerously complicated. Walter and I don't
>>>> think the aggravation is justified.
>>>>
>>>> There are of course more angles and considerations. Walter and I
>>>> discussed such for a while and concluded we should take the following
>>>> route:
>>>>
>>>> 1. For the time being, rollback the changes. Kenji, could you please do
>>>> the honors? There's no need to undo everything, only the key parts in
>>>> object.d. Apologies for having to undo your work!
>>>>
>>>> 2. Investigate a robust migration path from the current use of opCmp,
>>>> opEquals, toHash (we need to also investigate toString) to a world in
>>>> which these methods don't exist in Object. In that world, associative
>>>> arrays would probably be entirely generic. Ideally we should allow
>>>> existing code to still work, while at the same time fostering a better
>>>> style for new code.
>>>>
>>>>
>>>> What say you?
>>>>
>>>> Andrei
>>>
>>> Well:
>>> * having opCmp() defined for all objects is just plain weird.
>>> * toString() is a poor design anyway.
>>>
>>> But we'd need to be very careful, this is a very disruptive change.
>>
>> I don't find them that weird, because many OO languages do have them.
>
> Really? I find that incredible. Ordered comparisons <, > don't even make sense for many mathematical objects!
> You can't even define opCmp for a float.
>
> Object f = new FtpConnection;
> Object e = new Employee("Bob");
> if (f > e)  // Huh???

Silly me. I forgot that in D opCmp is more than just equality.

toString() I find it helpful specially in the cases where objects don't give enough external information. This is usable in scenarios where printf debugging is the only way.

Then again, it relies on the developer to have written a sensible toString() to start with.

On second thought you're probably right.

--
Paulo

July 12, 2012
On 12/07/2012 15:49, Andrei Alexandrescu wrote:
> On 7/12/12 9:39 AM, Steven Schveighoffer wrote:
>> On Thu, 12 Jul 2012 09:20:47 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 7/12/12 3:59 AM, Jonathan M Davis wrote:
>>>> If you can figure out how to make this work, it's fine by me.
>>>>
>>>> However, I see two potential issuses which cause currently working
>>>> idioms to
>>>> no longer work:
>>>>
>>>> 1. Anything which wants to be able to operate on Objects generically
>>>> (e.g.
>>>> have a container full of Objects) is going to have problems, since
>>>> comparison
>>>> and hashing won't work anymore. For the standard stuff, at minimum,
>>>> that will
>>>> screw up being able to put Object in AAs and RedBlackTree. For 3rd
>>>> party
>>>> containers which decided to go the Java route of containing Objects,
>>>> they risk
>>>> being completely screwed.
>>>
>>> I've been thinking more about this and it's possible to keep good
>>> backwards compatibility by "marginalizing" instead of eliminating the
>>> four culprits.
>>>
>>> Consider:
>>>
>>> class A { void fun() {} }
>>> class B : A { void fun() {} }
>>> class C : A {}
>>> void main() {
>>> A objA = new A;
>>> A objB = new B;
>>> A objC = new C;
>>> assert((&objA.fun).funcptr != (&objB.fun).funcptr);
>>> assert((&objA.fun).funcptr == (&objC.fun).funcptr);
>>> }
>>>
>>> In brief there _is_ a way to check during runtime whether a class has
>>> overridden a method.
>>>
>>> If we define alternative free generic functions in object.d for the
>>> four culprit methods (and have the compiler, druntime, and stdlib use
>>> them instead of the methods), those functions can check whether a
>>> given class object has overridden the old-style functions. In that
>>> case, that means we're dealing with legacy classes and proceed the
>>> old-style way. Otherwise, proceed the new way.
>>
>> Hm... I don't like this, it slows down a very basic function.
>
> It's one comparison.
>

And one branching. In itself it isn't high cost, but can become a problem in a tight loop, say a sort function for instance.
July 12, 2012
On Thu, Jul 12, 2012 at 12:59:16AM -0700, Jonathan M Davis wrote: [...]
> 1. Anything which wants to be able to operate on Objects generically (e.g.  have a container full of Objects) is going to have problems, since comparison and hashing won't work anymore. For the standard stuff, at minimum, that will screw up being able to put Object in AAs and RedBlackTree. For 3rd party containers which decided to go the Java route of containing Objects, they risk being completely screwed.
[...]

What about adding this to object.di:

	class Hashable : Object {
		int opCmp(Hashable h) @safe const { ... }
		bool opEquals(Hashable h) @safe const { ... }
		hash_t toHash() @safe const { ... }
	}

Whatever objects need to be put in AAs can just inherit from Hashable.

Or will this introduce more problems than it solves?


T

-- 
Кто везде - тот нигде.
July 12, 2012
On 12/07/2012 13:21, bearophile wrote:
> Andrei Alexandrescu:
>
>> What say you?
>
> It's an interesting proposal, and I like it in general.
>
> In D the C++-improved template system and the Java-copied OOP are
> partially a duplication, they sometimes offer two different ways to do
> similar things. I think this proposal reduces this duplication a bit.
>
> This whole discussion comes mostly from fixing an old Bugzilla bug. What
> other important bugs are open that risk requiring significant changes in
> D? I suggest to look for such breaking bug fixes asap, instead of
> waiting 2+ more years to find some bug that requires more important D
> changes to be fixed :-)
>
> Bye,
> bearophile

I'm thinking fo it for a while. This would be great to have a corpus of D code from volunteer project that can be used to test how much breakage does a disruptive change.

For this one, I bet not that much, but that is hard to assert without real world data.
July 12, 2012
On 7/12/12 10:40 AM, deadalnix wrote:
> And one branching. In itself it isn't high cost, but can become a
> problem in a tight loop, say a sort function for instance.

Cost should be assessed in comparison to the baseline work that is being performed. At any rate, the branch predictor should take care of branches that mostly go one way in a loop.

Andrei