March 19, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 19/03/2013 00:46, Jonathan M Davis wrote: > On Tuesday, March 19, 2013 00:26:40 Stewart Gordon wrote: <snip> >> Why can't it be used as a means of lazy initialization? > > Because if one of the member variables hasn't been initialized yet, then it > can't be compared. You miss the whole point of what I'm saying. Why can't some result stored in an out-of-object cache be used as a substitute for a member variable? <snip> > There _are_ types which _can't_ have const on opEquals, because they _need_ to > be able to mutate state in opEquals (e.g a lazily initialized object). They > may very well be logically const, but they're not physically const. <snip> This lazily initialised data would be calculated from the data already in the object, right? So why can't it just calculate the equality directly from that data? Even if it is computationally expensive to determine whether two objects of a given class are equal, why does it absolutely need to put the intermediate data into the object? Why can't it just use local variables to hold this intermediate data? In extreme cases, even make mutable copies of the objects to be compared and call the non-const opEquals on those? What I'm suggesting may be inefficient in complicated cases, but that's different from being impossible, which is what you're basically saying. Moreover, all this talk seems hypothetical. I'm yet to see anybody post a real-world example of what is being talked about, let alone one that will affect the typical everyday D programmer. Having some examples would help put the problem in better perspective. Stewart. |
March 19, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stewart Gordon | On Tuesday, March 19, 2013 01:31:23 Stewart Gordon wrote: > What I'm suggesting may be inefficient in complicated cases, but that's different from being impossible, which is what you're basically saying. It _is_ impossible if it's in the type, because you can't modify const. Sure, in same cases, you can put the data outside the type, but that's often undesirable. > Moreover, all this talk seems hypothetical. I'm yet to see anybody post a real-world example of what is being talked about, let alone one that will affect the typical everyday D programmer. Having some examples would help put the problem in better perspective. It's been discussed ad nauseum before. Go digging through old threads if you want more details. I'm just telling you want the plan is. Requiring opEquals and friends prevents certain idioms, and we have no reason to prevent those idioms - especially in a systems programming language. And every time that we've discussed making any of them const, a number of people have complained quite loudly. Some of them have real world code that would be negatively affected, but it's not mine, so I don't remember all of the nitty gritty details. It's been a big debate for some time how to resolve the problem given than some use cases require const and others require mutable. In the last big discussion, someone pointed out that opEquals and friends don't even need to be on Object in the first place, and that's what we decided on. And we don't really lose anything by removing them. Then, just like with structs, classes that want opEquals to be const can make it const, and those that don't want to, don't have to. - Jonathan M Davis |
March 19, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter Williams | On 19/03/2013 01:17, Peter Williams wrote: <snip> > Am I right in thinking that removal of these methods from Object will > mean that it will no longer be necessary for the the argument to be of > type Object Yes, and that's indeed a potentially good reason to remove opCmp and opEquals from Object, and one I'd thought of myself but hadn't got round to bringing into the conversation. > and that the need for casting in the implementation will go away? The need to cast from Object to some class just to compare objects of that class will go away, but you might still have similar casts it if you have a class with a comparator and you create subclasses of it. Stewart. |
March 19, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter Williams | On Tuesday, March 19, 2013 02:17:28 Peter Williams wrote:
> Am I right in thinking that removal of these methods from Object will mean that it will no longer be necessary for the the argument to be of type Object and that the need for casting in the implementation will go away?
Well, IIRC, if when you override a function, and you give it a different parameter type, it's a new overload rather than actually overriding anything (even if the type of the parameter in the derived type's function is a derived type of the type of the parameter in the base class' function). So, if you don't use a common type for the parameter, you'll run into overload conflicts regardless. So, while you _could_ use something other than Object, you could run into overload conflicts if you do. That can be gotten around by aliasing base class functions into the scope of the derived class (though that may cause derived types to be compared as base types if they're referred to via references to the base type, so that may no be a good idea) or by creating overloads for comparing every base class, but it's arguably easier to just accept Object and cast - or accept whatever the base type is which first introduces opEquals into the hierarchy.
So, there's a good chance that what you'll end up doing is using the base type in the hierarchy which introduces opEquals as the parameter for opEquals. This is better than using Object in that it'll avoid having completely unrelated types even be comparable (as their opEquals wouldn't accept each other), but it would still require derived types to use that type as the parameter type for opEquals for the reasons mentioned above.
- Jonathan M Davis
|
March 19, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
On 19/03/13 15:38, Jonathan M Davis wrote:
> On Tuesday, March 19, 2013 02:17:28 Peter Williams wrote:
>> Am I right in thinking that removal of these methods from Object
>> will mean that it will no longer be necessary for the the
>> argument to be of type Object and that the need for casting in
>> the implementation will go away?
>
> Well, IIRC, if when you override a function, and you give it a different
> parameter type, it's a new overload rather than actually overriding anything
> (even if the type of the parameter in the derived type's function is a derived
> type of the type of the parameter in the base class' function). So, if you
> don't use a common type for the parameter, you'll run into overload conflicts
> regardless. So, while you _could_ use something other than Object, you could
> run into overload conflicts if you do. That can be gotten around by aliasing
> base class functions into the scope of the derived class (though that may
> cause derived types to be compared as base types if they're referred to via
> references to the base type, so that may no be a good idea) or by creating
> overloads for comparing every base class, but it's arguably easier to just
> accept Object and cast - or accept whatever the base type is which first
> introduces opEquals into the hierarchy.
>
> So, there's a good chance that what you'll end up doing is using the base type
> in the hierarchy which introduces opEquals as the parameter for opEquals. This
> is better than using Object in that it'll avoid having completely unrelated
> types even be comparable (as their opEquals wouldn't accept each other), but
> it would still require derived types to use that type as the parameter type
> for opEquals for the reasons mentioned above.
>
> - Jonathan M Davis
>
Yes. I didn't mean to imply that all casting would go away just the OBLIGATORY casting of Object.
Peter
PS I'd like to say that this is the first disappointment I've encountered in my mission to learn D. Otherwise, I'm finding it a pleasure to use and find the compiler error messages very useful compared to those I'm used to with similar languages. Well done!!
|
March 19, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 19/03/2013 05:38, Jonathan M Davis wrote: <snip> > Well, IIRC, if when you override a function, and you give it a > different parameter type, it's a new overload rather than actually > overriding anything (even if the type of the parameter in the derived > type's function is a derived type of the type of the parameter in the > base class' function). I've just been reminding myself of what http://dlang.org/hijack.html says about this. As it turns out, they are indeed separate overloads, albeit protected by hiding the base class's version from derived class references. > So, if you don't use a common type for the parameter, you'll run into > overload conflicts regardless. So, while you _could_ use something > other than Object, you could run into overload conflicts if you do. > That can be gotten around by aliasing base class functions into the > scope of the derived class (though that may cause derived types to be > compared as base types if they're referred to via references to the > base type, so that may no be a good idea) or by creating overloads > for comparing every base class, but it's arguably easier to just > accept Object and cast - or accept whatever the base type is which > first introduces opEquals into the hierarchy. <snip> I've always defined both opEquals(Object) and opEquals(MyClass), and likewise for opCmp where applicable, and made the Object version call the class-specific version. This way, the overhead of a cast is avoided in the case where you're comparing two objects through references of the specific class type. Of course, once these are removed from Object, it will just be a case of removing the Object versions of these methods from my class. But the question still remains: How do we implement this change without causing mass disruption? It might be the case that programmers just need to remove opEquals(Object) and opCmp(Object) from their classes, and remove the override attribute from toHash and toString (and declare them const as appropriate). But there will be a lot of libraries to convert, and it will take time for them all to be converted. Stewart. |
March 20, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stewart Gordon | On Tuesday, March 19, 2013 20:51:28 Stewart Gordon wrote:
> But the question still remains: How do we implement this change without causing mass disruption? It might be the case that programmers just need to remove opEquals(Object) and opCmp(Object) from their classes, and remove the override attribute from toHash and toString (and declare them const as appropriate). But there will be a lot of libraries to convert, and it will take time for them all to be converted.
I expect that we'll figure out how to do that when we're ready to actually start the transition process, but the obvious thing to do to start with would be to deprecate opEquals, opCmp, toHash, and toString on Object, which should then cause a number of deprecation warnings. That likely wouldn't be enough, but it would be a start. Additional compiler warnings would probably need to be added at some point, and eventually those functions would be outright removed. But regardless of how it's approached, it's obviously going to require changing existing code, and it's going to be disruptive. We can't avoid that, just mitigate it. But it _is_ a change that we're going to need to make in order to solve some of the problems surrounding opEquals et al and const. The main issue at this point is gettnig the work necessary to be able to make the transition done (and since that includes changes to the AA implementation, it's far from a small undertaking).
- Jonathan M Davis
|
March 21, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter Williams | On Monday, March 18, 2013 00:19:03 Peter Williams wrote:
> So my question is "Why are the arguments to opEquals and opCmp (for Objects) not declared in or const?".
By the way, this is post where it was officially decided that we'd be working on removing opCmp, opEquals, toHash, and toString from Object. It also has a link to the prior discussion. Apparently, all that was way back in July. Man, how time flies...
- Jonathan M Davis
|
March 21, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Wednesday, 20 March 2013 at 04:39:14 UTC, Jonathan M Davis wrote:
> On Tuesday, March 19, 2013 20:51:28 Stewart Gordon wrote:
>> But the question still remains: How do we implement this change without
>> causing mass disruption? It might be the case that programmers just
>> need to remove opEquals(Object) and opCmp(Object) from their classes,
>> and remove the override attribute from toHash and toString (and declare
>> them const as appropriate). But there will be a lot of libraries to
>> convert, and it will take time for them all to be converted.
>
> I expect that we'll figure out how to do that when we're ready to actually
> start the transition process, but the obvious thing to do to start with would
> be to deprecate opEquals, opCmp, toHash, and toString on Object, which should
> then cause a number of deprecation warnings. That likely wouldn't be enough,
> but it would be a start. Additional compiler warnings would probably need to
> be added at some point, and eventually those functions would be outright
> removed. But regardless of how it's approached, it's obviously going to
> require changing existing code, and it's going to be disruptive. We can't
> avoid that, just mitigate it. But it _is_ a change that we're going to need to
> make in order to solve some of the problems surrounding opEquals et al and
> const. The main issue at this point is gettnig the work necessary to be able
> to make the transition done (and since that includes changes to the AA
> implementation, it's far from a small undertaking).
>
> - Jonathan M Davis
Wouldn't that trigger bunch of false warning on legitimate overloaded opSomething ?
|
March 21, 2013 Re: Why are opEquals/opCmp arguments not in or const for Objects? | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On Thursday, March 21, 2013 08:29:28 deadalnix wrote:
> Wouldn't that trigger bunch of false warning on legitimate overloaded opSomething ?
I'm not sure that overriding a deprecated function triggers a deprecation warning, but regardless, for opEquals and opCmp, that wouldn't be a problem, because all classes would be being changed so that their opEquals and opCmp don't take Object, so the deprecation warnings would be a _good_ thing. It would probably be more of a problem for toString and toHash though, since they don't take arguments. Deprecating them won't work if overriding them triggers deprecation warnings, and the fact that you'll be forced to override them as long as they're in Object and then won't be allowed to once they're out of Object will probably mean simply removing them from one release to another and forcing everyone to immediately change their toHash and toString methods so that they don't break.
So no, the situation isn't entirely clear-cut, and we'll have to look at it carefully to avoid as much immediate breakage as possible, but we may be forced to change some stuff in a way that causes immediate breakage. All that would depend on what the exact changes are that have to be made and the exact situation with override and deprecated and all that. And I don't think that anyone has thought that through completely yet.
- Jonathan M Davis
|
Copyright © 1999-2021 by the D Language Foundation