May 14, 2012
On Sunday, 13 May 2012 at 22:51:05 UTC, Jonathan M Davis wrote:
> Walter fully intends to require that opEquals, opCmp, toHash, and toString all be const @safe pure nothrow - on both classes and structs. And the reality of the matter is, if that requirement _isn't_ there on classes, then the usage of any of those functions in @safe, const, pure, or nothrow code is seriously hampered - especially const and pure. This has been discussed quite a bit before, and we're pretty much stuck thanks to transitivity.

 I've been wondering sometimes, if beta builds could be made (but not official release builds) that enforce the way it's suppose to be, and then we can try to compile against that version and see how much difference or how much breaks. The problem may not be quite as bad as we think it is. Honestly I don't see why oEquals, opCmp and toHash can't be const (as the data shouldn't change). toString and toHash may want to cache it's current result (perhaps?).


May 14, 2012
On Monday, May 14, 2012 02:11:21 Era Scarecrow wrote:
> On Sunday, 13 May 2012 at 22:51:05 UTC, Jonathan M Davis wrote:
> > Walter fully intends to require that opEquals, opCmp, toHash, and toString all be const @safe pure nothrow - on both classes and structs. And the reality of the matter is, if that requirement _isn't_ there on classes, then the usage of any of those functions in @safe, const, pure, or nothrow code is seriously hampered - especially const and pure. This has been discussed quite a bit before, and we're pretty much stuck thanks to transitivity.
> 
>   I've been wondering sometimes, if beta builds could be made (but
> not official release builds) that enforce the way it's suppose to
> be, and then we can try to compile against that version and see
> how much difference or how much breaks. The problem may not be
> quite as bad as we think it is.

It doesn't work right now due to issues with druntime and Phobos. For instance, format and to!string can't be pure yet due to lower level constructs that they use which aren't marked pure. Appender has similar problems. Without those, toString really can't be const. I think that there are some issues with toHash as well due to the state of the AA implementation in druntime. Some of those issues are being addressed, but there's still a ways to go.

But in a way, it doesn't matter how much making those 4 functions const @safe pure nothrow will break, because we _have_ to do it. So, what will break, will break. When they're made const @safe pure nothrow on Object, it'll _immediately_ break code, and there's _no_ way around it. So, at this point, I'd say that it's really a matter of figuring out exactly what needs to be fixed in druntime and Phobos to make it possible, and once that's been fixed, we immediately change Object and and require that those 4 functions have those 4 attributes. Then everyone can take care of it in their code at once and we won't have to worry about it anymore. Lacking a means of phasing it in (like we're doing with other stuff like -property), I don't see any other way of doing it.

> Honestly I don't see why oEquals,
> opCmp and toHash can't be const (as the data shouldn't change).
> toString and toHash may want to cache it's current result
> (perhaps?).

They can be in almost all cases. The problem is the folks who want to have caching and/or lazy initiailization in their classes/structs. You can't cache the result of any of those functions (toHash being the main target for it) if they're const and pure except in overloads which _aren't_ const, making those functions more expensive in comparison to what they could be if they weren't required to be const. And lazy initialization becomes almost impossible, because if the member variables needed in those functions haven't been initialized yet when they're called, then you _can't_ initialize them. If getting the value that it _would_ be without actually initializing the member variable works, then you can do that if it hasn't been initialized, but if you can't do that (e.g. the variable _must_ be set only once), then you're screwed. And regardless of whether you can make it work with const, it _will_ be less efficient.

So, the folks who really like to use lazy initialization and caching are _not_ going to be happy about this. They've complained every time that it's been discussed. But that's just one of the costs of const in D. Whether its pros outweigh that cost is a matter of opinion.

- Jonathan M Davis
May 14, 2012
On Monday, 14 May 2012 at 02:48:20 UTC, Jonathan M Davis wrote:
> But that's just one of the costs of const in D.


The problem is that it's unavoidable.

i.e. you can't say "don't mark it as const if it isn't const", because, practically speaking, it's being forced onto the programmers by the language.
May 14, 2012
On Monday, 14 May 2012 at 02:57:57 UTC, Mehrdad wrote:
> On Monday, 14 May 2012 at 02:48:20 UTC, Jonathan M Davis wrote:
>> But that's just one of the costs of const in D.
>
> The problem is that it's unavoidable.
>
> I.e. you can't say "don't Mark it as const if it isn't const", because, practically speaking, it's being forced onto the programmers by the language.

 With const and immutable being transitive, there are cases when there's things you want to do with an object after you've made it and it's in a const structure. I know I've made a struct that was intended to hold immutable data, however it refused to allow methods to until const was appended to the signatures of the functions. At first it was annoying; But when I see bigger picture of why it makes much more sense.

 Nothing we make 'has' to have const on it but inevitably they may be used in a read-only way. I'm trying to think of it as my structs and classes being as const-friendly as possible in those cases.
May 14, 2012
On Monday, May 14, 2012 05:09:28 Era Scarecrow wrote:
> On Monday, 14 May 2012 at 02:57:57 UTC, Mehrdad wrote:
> > On Monday, 14 May 2012 at 02:48:20 UTC, Jonathan M Davis wrote:
> >> But that's just one of the costs of const in D.
> > 
> > The problem is that it's unavoidable.
> > 
> > I.e. you can't say "don't Mark it as const if it isn't const", because, practically speaking, it's being forced onto the programmers by the language.
> 
>   With const and immutable being transitive, there are cases when
> there's things you want to do with an object after you've made it
> and it's in a const structure. I know I've made a struct that was
> intended to hold immutable data, however it refused to allow
> methods to until const was appended to the signatures of the
> functions. At first it was annoying; But when I see bigger
> picture of why it makes much more sense.
> 
>   Nothing we make 'has' to have const on it but inevitably they
> may be used in a read-only way. I'm trying to think of it as my
> structs and classes being as const-friendly as possible in those
> cases.

In general, you _can_ avoid const completely if you want to. However, with opEquals, opCmp, toHash, and toString being const @safe pure nothrow, you _can't_ avoid it completely - at least not entirely cleanly.

You could have non-const overloads which did what you wanted and make the normal const ones assert(0) if they're called. But you're basically forced to work around const in this case. This is in definite contrast to C++ where you _can_ avoid const completely if you want to.

But with the way const in D works, I suspect that the folks who are looking for absolutely every CPU cycle and want caching and lazy-loading in their types are going to avoid const as completely as possible and figure out how to work around it for those 4 functions, whereas in C++, they'd probably use const liberally and use mutable where necessary.

- Jonathan M Davis
May 14, 2012
On Monday, 14 May 2012 at 03:19:57 UTC, Jonathan M Davis wrote:
> But with the way const in D works, I suspect that the folks who are looking for absolutely every CPU cycle and want caching and lazy-loading in their types are going to avoid const as completely as possible and figure out how to work around it for those 4 functions, whereas in C++, they'd probably use const liberally and use mutable where necessary.>

 Seems like perhaps the opposite approach (limited of course) could be taken. Assume a 'mutable' keyword was used, where in the case an object/struct was made const, it would allow you to break the const system only for that variable. Could work, assuming it's not accessing ROM or something.

struct A {
  string st;
  mutable uint hash; //always mutable

  uint toHash() {
    if (!hash)
      hash = st.toHash();
    return hash;
  }
}

unittest{
  A a = A("TEST");
  immutable A b = A("TEST");

  assert(a.toHash() == b.toHash());
}

 But that seems like a badly done workaround, and if you really wanted the hash cached, you would have it calculated during construction before it was returned. Something like that is likely more trouble than it's worth, plus it would easily be abused.
May 14, 2012
On 5/13/2012 8:19 PM, Jonathan M Davis wrote:
> This is in definite contrast to C++ where you
> _can_ avoid const completely if you want to.

That's because C++ const is just documentation for the programmer, and offers no reliable enforcement.
May 14, 2012
On 14-05-2012 05:19, Jonathan M Davis wrote:
> On Monday, May 14, 2012 05:09:28 Era Scarecrow wrote:
>> On Monday, 14 May 2012 at 02:57:57 UTC, Mehrdad wrote:
>>> On Monday, 14 May 2012 at 02:48:20 UTC, Jonathan M Davis wrote:
>>>> But that's just one of the costs of const in D.
>>>
>>> The problem is that it's unavoidable.
>>>
>>> I.e. you can't say "don't Mark it as const if it isn't const",
>>> because, practically speaking, it's being forced onto the
>>> programmers by the language.
>>
>>    With const and immutable being transitive, there are cases when
>> there's things you want to do with an object after you've made it
>> and it's in a const structure. I know I've made a struct that was
>> intended to hold immutable data, however it refused to allow
>> methods to until const was appended to the signatures of the
>> functions. At first it was annoying; But when I see bigger
>> picture of why it makes much more sense.
>>
>>    Nothing we make 'has' to have const on it but inevitably they
>> may be used in a read-only way. I'm trying to think of it as my
>> structs and classes being as const-friendly as possible in those
>> cases.
>
> In general, you _can_ avoid const completely if you want to. However, with
> opEquals, opCmp, toHash, and toString being const @safe pure nothrow, you
> _can't_ avoid it completely - at least not entirely cleanly.

Don't forget contracts. The this reference is now const inside those too. This can get painful sometimes when you really don't want the this reference to be const inside your invariants. With 2.058, I had to insert a lot of cast()s to throw const away inside those. So... effectively, it's pretty hard to avoid const unless you don't use contracts at all.

>
> You could have non-const overloads which did what you wanted and make the
> normal const ones assert(0) if they're called. But you're basically forced to
> work around const in this case. This is in definite contrast to C++ where you
> _can_ avoid const completely if you want to.
>
> But with the way const in D works, I suspect that the folks who are looking
> for absolutely every CPU cycle and want caching and lazy-loading in their
> types are going to avoid const as completely as possible and figure out how to
> work around it for those 4 functions, whereas in C++, they'd probably use
> const liberally and use mutable where necessary.
>
> - Jonathan M Davis

It's kinda funny that something which on dlang.org's FAQ is described as a compiler optimization hint (http://dlang.org/const-faq.html#const) isn't useful at all for this purpose...

-- 
- Alex
May 14, 2012
On Monday, 14 May 2012 at 02:57:57 UTC, Mehrdad wrote:
> The problem is that it's unavoidable.
>
> i.e. you can't say "don't mark it as const if it isn't const", because, practically speaking, it's being forced onto the programmers by the language.

You're really against const in this language, huh?

Let me ask you something: Could you try to name 2 or 3 good
things about const/immutable without looking it up? If not,
you've really not given enough effort to learning about the
benefits of it.
May 14, 2012
On Monday, May 14, 2012 05:47:54 Alex Rønne Petersen wrote:
> It's kinda funny that something which on dlang.org's FAQ is described as a compiler optimization hint (http://dlang.org/const-faq.html#const) isn't useful at all for this purpose...

Oh, it's definitely useful for optimizations. It just doesn't work with a couple of idioms that some programmers like to use in order to optimize their code.

- Jonathan M Davis