View mode: basic / threaded / horizontal-split · Log in · Help
May 14, 2012
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
Re: Getting the const-correctness of Object sorted once and for all
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
1 2 3 4 5 6 7
Top | Discussion index | About this forum | D home