August 19, 2012
On Sunday, 19 August 2012 at 19:42:20 UTC, Peter Alexander wrote:
> On Sunday, 19 August 2012 at 19:26:58 UTC, Jesse Phillips wrote:
>> While in context with the original question this is fine, but I do not like this use of guarantee.
>>
>> What I mean is, const does provide guarantees by itself. And it provides more than C++ because it is transitive and modifying a const reference is undefined.
>
> What guarantees does const provide on its own?

 If you don't circumvent the language by casting/forcing it, then const (and immutable) items cannot be changed by the functions called with them, nor them nor anything they contain or reference.

 In cases of methods to classes/structs, const ensures the object (allocated separately in each variable/heap location) won't change in any way.

 Isn't that good enough?

 It's like asking what guarantees a book contains it's data. It's entirely guaranteed as long you don't use a permenant marker, rip the pages out, burn it, soak it in a bath tub full of water or acid, run it over, throw it in lava, bleach it, or send it through a trans-dimensional portal to another universe. or any number of other things, but that's outside the scope of the publisher's ability to after providing the book; when left untouched the book should always contain the data.

 Isn't that good enough?
August 19, 2012
On Sunday, 19 August 2012 at 19:58:11 UTC, Era Scarecrow wrote:
> On Sunday, 19 August 2012 at 19:42:20 UTC, Peter Alexander wrote:
>> On Sunday, 19 August 2012 at 19:26:58 UTC, Jesse Phillips wrote:
>>> While in context with the original question this is fine, but I do not like this use of guarantee.
>>>
>>> What I mean is, const does provide guarantees by itself. And it provides more than C++ because it is transitive and modifying a const reference is undefined.
>>
>> What guarantees does const provide on its own?
>
>  If you don't circumvent the language by casting/forcing it, then const (and immutable) items cannot be changed by the functions called with them, nor them nor anything they contain or reference.

class Foo
{
    static Foo sneaky;
    this() { sneaky = this; }
    void bar() const { sneaky.x++; }
    int x = 0;
}

const(Foo) f = new Foo();
assert(f.x == 0);
f.bar();
assert(f.x == 1);


You only have that guarantee if there are no other mutable references to the data. const *on its own* does not provide that guarantee.
August 19, 2012
On Sunday, 19 August 2012 at 20:14:50 UTC, Peter Alexander wrote:
> class Foo
> {
>     static Foo sneaky;
>     this() { sneaky = this; }
>     void bar() const { sneaky.x++; }
>     int x = 0;
> }
>
> const(Foo) f = new Foo();
> assert(f.x == 0);
> f.bar();
> assert(f.x == 1);
>
> You only have that guarantee if there are no other mutable references to the data. const *on its own* does not provide that guarantee.

 I don't think 'sneaky' counts. Static being there's only one of basically takes it outside the scope of the class/struct in it's own memory space. Re-written it's treated like this.

Foo sneaky;

class Foo
{
    this() { sneaky = this; }
    void bar() const { sneaky.x++; }
    int x = 0;
}

const(Foo) f = new Foo();
assert(f.x == 0);
f.bar();
assert(f.x == 1);

const(Foo) f2 = new Foo(); //a WTF moment?

assert(f.x == 1);
f.bar();
f.bar();
assert(f.x == 1);
assert(f2.x == 2);

 Besides likely the const/immutable and constructors can likely fix this, or maybe not. *shrugs* More likely the failures. In truth bar never modifies the allocated data (being Foo.x), sneaky although a reference is considered it's own thing.

 Besides weren't not talking about the data never changing, only the code calling can't change it (directly). If you don't want things to change, then A) don't write it to circumvent it, or B) Use immutable (then do Step A again)
August 19, 2012
On Sunday, August 19, 2012 22:14:49 Peter Alexander wrote:
> You only have that guarantee if there are no other mutable references to the data. const *on its own* does not provide that guarantee.

Yeah. If you really want to get down to the nitty gritty of when exactly the compiler can guarantee that a const object won't change even through other references, then you're restricted to cases where the compiler _knows_ that no other mutable references exist, which is very restrictive. But in practice, it buys you a lot more, and not only because of pure. For instance, if I have a class that holds a container, and the only place that that data leaves my class is its getter

@property const(Array!T) myContainer() const {...}

then I know that no one using the getter is going to mess with the container. I know that there's no way that they can possibly screw with my container or its contents via the getter. And since of course, I won't have written screwy stuff into my class like having the container really point to a global or even be set via a setter, I know that they won't even be able to mess with the container via another reference. And if I control where the elements come from, then I can know that the elements won't be messed with by any other references either, because I'll know that there are no other references to them.

Sure, the compiler may not be able to optimize much (if anything) there, but it really helps you reason about your code - especially when it comes to giving access to member variables to code outside your class or struct. So, the combination of transivity and illegality of mutating const (even through casting) does actually buy you quite a lot. Yes, adding in pure or immutable buys you a lot more, but that doesn't mean that const is useless without them.

- Jonathan M Davis
September 07, 2012
On Thu, 16 Aug 2012 18:14:27 -0400, Mehrdad <wfunction@hotmail.com> wrote:

> Something I'm having trouble undertanding/remembering (sorry, you've probaby already explained it a billion times)...
>
> I remember being told many times that D's 'const' provides stronger guarantees than C++'s 'const'.
>
> I just wanted to clarify, is that true for 'const' itself, or is that referring only to when 'const' is used with other D-specific features (immutable, etc.)?


I know this is old, just going through my backlog of unread newsgroup posts.

someone else correctly pointed out that const guarantees make it a viable interface for both immutable and mutable data.  In other words, it provides the ability to write a function that accepts both mutable and immutable data, rather than having to write two such functions that would be identical.

I look at it like this:

immutable provides guarantees such that statically-checked pure is possible.
const provides guarantees such that I don't have to repeat myself for everything!
inout provides similar benefits as const, but allows me to to use chaining without repeating myself for everything.

>
> If it's the former, is there some example piece of code in each language, for comparison, that shows how the compiler can infer more from D's const than C++'s?

It's the latter, not the former.  The compiler cannot make any assumptions unless the other guarantees (particularly immutable) are involved.

For example, consider the following function:

int foo(const int *x, int *y)
{
   *y += *x;
   return *x;
}

If compiled without any context, the compiler *must* re-load *x from memory, because potentially x == y.

However, if called like this:

int bar(immutable int *x, int *y)
{
   return foo(x, y);
}

now, if foo is inlined inside of bar, it *can* make the assumption that x != y, and so a reload of *x is not necessary (it must be unchanged).

-Steve
1 2 3 4 5 6 7 8
Next ›   Last »