View mode: basic / threaded / horizontal-split · Log in · Help
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, August 17, 2012 02:32:01 Mehrdad wrote:
> On Friday, 17 August 2012 at 00:10:52 UTC, Jonathan M Davis wrote:
> > In C++, if you have
> > 
> > const vector<T*>& getStuff() const;
> > 
> > which returns a member variable, then as long as const isn't
> > cast away, you know that the container itself won't have any
> > elements added or removed from it, but you have _zero_
> > guarantees about the elements themselves.
> 
> Right.
> 
> > In contrast, in D,
> > 
> > const ref Array!(T*) getStuff() const;
> > 
> > you would _know_ that not only is the container not altered,
> > but you know that the elements aren't altered either -
> > or anything which the elements point to.
> 
> I'm not so sure about that.
> 
> int yourGlobalCounter;
> 
> struct MyIntPtrArray
> {
> int*[] items;
> 
> MyIntPtrArray()
> {
> items = new int*[1];
> items[0] = &yourGlobalField;
> }
> 
> ref const(int*[]) getItems() const
> {
> ++yourGlobalCounter;
> return items;
> }
> }

What I meant is that you know that nothing was altered through the reference 
that the getter returned. You don't have any such guarantee in C++.

But even if both the constructor and getItems are pure, you could still pass 
the initial value of items in as an argument to the constructor making it so 
that there are potentially references to it outside MyIntPtrArray, which is 
why immutable buys you so much.

So, the optimizations permitted by const alone (and to some extent even with 
pure) do tend to be fairly localized precisely because of the number of ways 
that the const variable could refer to data which is altered by other, mutable 
references to it.

- Jonathan M Davis
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, August 17, 2012 03:59:01 Chris Cain wrote:
> If you're absolutely 100% completely totally certain that the
> data is mutable (i.e., you have confirmed either through good,
> sound reasoning OR you have some method of seeing exactly where
> it is stored in your RAM and you've checked that the place it is
> stored is writable memory), then __technically__, yes you can
> cast away and modify away. Apparently, according to some, it's
> necessary for low level programming. I'd highly discourage this
> type of behavior because if you're doing something like that I'm
> nearly certain you could come up with a better design, not to
> mention you're missing the point of having something const in the
> first place.

It's still technically undefined behavior. It's just that there's pretty much 
no way that the compiler is going to be written in a way that it won't work. 
However, you _do_ still risk running into problems because the compiler may 
make optimizations that you're violating by modifying the object. So, even if 
you're _certain_ that the object is actually mutable and you're _certain_ that 
nothing will blow up when you cast away const and modify it, you _still_ could 
get bugs due to compiler optimizations.

- Jonathan M Davis
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, 17 August 2012 at 02:09:09 UTC, Mehrdad wrote:
> On Friday, 17 August 2012 at 02:02:56 UTC, Jonathan M Davis 
> wrote:
>> How is it a bug? The variable that you're altering is not part 
>> of the object.
>
>
> It doesn't need to be.


Not to say it /can't/ be, of course... a const method can 
certainly legally modify its own object's members. All you need 
is some aliasing.

http://forum.dlang.org/thread/gjccnstbihxbrwhwwucs@forum.dlang.org?page=3#post-mailman.1286.1345168975.31962.digitalmars-d:40puremagic.com
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, August 17, 2012 04:12:10 Mehrdad wrote:
> On Friday, 17 August 2012 at 02:02:51 UTC, Jonathan M Davis wrote:
> > Because there are plenty of functions which take mutable
> > objects but don't actually alter them - particularly when
> > interacting with C code.
> 
> Ah, so that explains that, thanks.
> 
> So to clarify, modifying a mutable object through casting away a
> const reference is undefined in D, but valid in C++.
> 
> Now the only question is what guarantees that actually gives you
> that the compiler can use for optimization (aliasing issue
> above^).

Yeah. It's more than C++, but it's still pretty limited without pure, and if
even with pure, the optimizations can still be pretty limited. Immutable gives
a _lot_ more. And while there's definitely optimizations to  be had with const,
I suspect that dmd doesn't exploit them very well at this point. Other issues
have had far higher priority than eking out every last bit of performance that
we can. So, regardless of what D's current performance is, I think that it's
pretty much a guarantee that it will improve as D matures.

- Jonathan M Davis
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, 17 August 2012 at 02:25:22 UTC, Jonathan M Davis wrote:
> Yeah. It's more than C++, but it's still pretty limited without 
> pure, and if even with pure, the optimizations can still be 
> pretty limited.

Yeah, I'm only worried about the language here, not the 
implementation.



On Friday, 17 August 2012 at 02:14:22 UTC, Jonathan M Davis wrote:
> What I meant is that you know that nothing was altered through 
> the reference that the getter returned. You don't have any such 
> guarantee in C++.


I'm not following..
It seems to contradict my second example:


struct MyStruct
{
	static int* x;
	int y;
	this() { }
	this(int* z) { x = z; }
	auto getValue() const { ++*x; return this.y; }
}
auto s = MyStruct();
s = MyStruct(&s.y);
s.getValue();  // const, but returns 1
s.getValue();  // const, but returns 2
s.getValue();  // const, but returns 3


So unless you're expecting the compiler to have the 
implementation for the entire class available in order for it to 
be able to do any kind of optimization (in which case, it would 
have to do a whole bunch of inference to figure out the aliasing 
issues, which would amount to what a C++ could try do just as 
well), I'm not seeing where the additional guarantees/potential 
optimizations are.
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, 17 August 2012 at 02:01:11 UTC, Mehrdad wrote:
>...snip...
>
> Are you sure?

I've already responded to something that is equivalent to what 
you just posted. I'm not sure if you're intentionally being 
obtuse (I'll give you the benefit of the doubt) or if your eyes 
are glossing over when you get to the important parts of my 
posts, but in either case I don't feel like repeating myself 
again. For your benefit, I'm repeating myself as clearly as I can:

Const is basically a view of your data. If you have something 
that's const, it's like looking through a filter that only allows 
you to do certain things. It is _not_ a guarantee that it's the 
only view of your data that exists in the universe. Your code, 
again, shows that you have two views of your memory. x is a 
mutable view of your data, and you're mutating it. y is your 
const view of your data. No matter how hard you try (without 
casts), you can't mutate y. You _can_ mutate x, which y is 
viewing. The y view updates accordingly, but you didn't mutate y.

Maybe in a second you'll say "oh, but that's mutating y" and I'll 
promptly ignore you completely this time because you've yet again 
missed the point:2

You mutated x, not y, y is a view on the same data that x is so 
mutating x would logically have y's view updated since const 
isn't a guarantee that you only have one view of the data and 
thus blah blah blah ... would be my ad infinitum response.



Let me point this out: It's there to give you guarantees and ways 
to think about your code and to allow you to use the same code 
for mutable and immutable data. That's it. There's no magic 
behind it that you're not getting. The idea is that if you want 
those particular features in your code and you know you can use 
them effectively, then you use const. Generally, if you want the 
same code to work on mutable data and immutable data, then you 
have to use const. It's a bridge that allows the same code to 
work with either type. You can use this so that you reduce code 
duplication (and work for you) or/and reduce the amount of 
instructions loaded in your CPU (potentially reducing the times 
when your cache is reloaded) or I'm sure there's other good 
reasons as well, but that's for you to figure out. It isn't a 
catch all feature. Not everything needs to be bashed with the 
const golden hammer of doom without any thought behind why you 
might want it to be const. There's plenty of times where you 
don't want to use const because it simply doesn't make sense and 
it doesn't give any additional meaning to your code. But that's 
okay, you just don't need to use const when it doesn't do 
anything for you.


Your main problem seems to be that you're intentionally trying to 
break const as hard as you can. Obviously, there's nonsensical 
ways to use const, and I don't think anyone would argue that 
_any_ feature is completely bulletproof to incompetence. Take 
classes for instance. Do I really need to give you an example 
that grossly misuses classes? Does that mean that classes have no 
purpose? Should I always use structs or parallel arrays because 
classes can be misused?

Instead of trying to misuse the feature, you ought to be spending 
your energy trying to use the feature for your benefit.


(I'm going to make this the last post on the matter ... I'll 
respond to Mr. Davis' concern on the bug in just a minute, but 
I've made my full effort to explain const to you and I don't see 
where additional conversation on my part can clarify this any 
further.)
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, 17 August 2012 at 02:02:56 UTC, Jonathan M Davis wrote:
>
> How is it a bug? The variable that you're altering is not part 
> of the object.
> That's part of why having pure with const in so valuable. It 
> prevents stuff
> like what you're doing here.
>
> - Jonathan M Davis

Notice that I'm making an immutable(S) in that example. It should 
then transitively mean that the data pointed to will be immutable 
as well. The reason this is a bug is because the constructor is 
currently set up to have the thing you're working with be mutable 
while you're still constructing it (otherwise, you couldn't even 
initialize any of the fields). However, this allows invalid code.

Here's a bit simplified version with some extra output:

int gCount;

struct S {
    int* it;
    this(int i) {
        writeln("--- constructor begin ---");
        gCount = i;
        it = &gCount; // Should be compile error
                      //when constructing immutable(S)
        writeln(typeof(it).stringof, " it = ", *it);
        writeln("^^ Notice, typeof(it) is always mutable!");
        writeln("--- constructor end ---");
    }
    ref const(int*) getItem() const {
        ++gCount;
        return it;
    }
}

import std.stdio;

void main() {
    immutable(S) s = immutable(S)(0);
    auto it = s.getItem();
    writeln(typeof(s.it).stringof, " s.it = ", *s.it);
    writeln(typeof(it).stringof, " it = ", *it);
    writeln(typeof(gCount).stringof, " gCount = ", gCount);
    s.getItem();
    writeln(typeof(s.it).stringof, " s.it = ", *s.it);
    writeln(typeof(it).stringof, " it = ", *it);
    writeln(typeof(gCount).stringof, " gCount = ", gCount);
}



I'm almost sure it's been reported before because I've seen talk 
about this particular issue in the past.

If you run this with optimizations off and on, it shows off the 
type of optimizations that can be made when something is 
immutable. For instance, with optimizations off you get:
...
immutable(int*) s.it = 1
const(int*) it = 1
int gCount = 1
immutable(int*) s.it = 2
const(int*) it = 2
int gCount = 2

and on:
...
immutable(int*) s.it = 1
const(int*) it = 1
int gCount = 1
immutable(int*) s.it = 1
const(int*) it = 2
int gCount = 2

As you can see, the optimization is that it doesn't even check 
s.it's memory location, it just puts the previous value in place.

But yeah, it's a bug that this code is allowed.
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, August 17, 2012 04:30:42 Mehrdad wrote:
> So unless you're expecting the compiler to have the
> implementation for the entire class available in order for it to
> be able to do any kind of optimization (in which case, it would
> have to do a whole bunch of inference to figure out the aliasing
> issues, which would amount to what a C++ could try do just as
> well), I'm not seeing where the additional guarantees/potential
> optimizations are.

It's probably going to be restricted to primitive types in many cases due to 
not knowing what member functions are doing. But take this code for example:

auto i = new int;
*i = 5;
const c = i;
writeln(c);
func(c); //obviously takes const or it wouldn't compile
writeln(c);

The compiler _knows_ that c is the same before and after the call to func, 
because it knows that no other references to that data can exist. And since 
it's a built-in type, it also knows that there's no way that any functions 
operating on func can wile away any mutable, global references to it. So, if 
we were doing something more interesting than writeln before and after func - 
something which could actually be optimized based on the knowledge that c is 
unchanged - then const alone is enough to guarantee that that optimization is 
valid. The same cannot be said of C++, which could cast away const on c inside 
of func and do who-knows-what to it.

If you use a class instead of int and take it one step further and simply make 
its constructor pure, then the compiler _still_ knows that the object is the 
same before and after the call to func, even if none of the class' other 
functions are pure, because it knows that no mutable references to the data 
can exist beyond i.

Once you're dealing with code which doesn't include the creation of the 
object, it's likely much harder to make any gurantees about it not being 
altered, because the compiler doesn't know whether any other references to the 
data exist or not, and then purity matters that much more, but if the compiler 
knows that no other references to the data exists, then const is enough, even 
if the object is passed to other functions, unlike with C++.

- Jonathan M Davis
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, 17 August 2012 at 02:33:46 UTC, Chris Cain wrote:
> I've already responded to something that is equivalent to what 
> you just posted. I'm not sure if you're intentionally being 
> obtuse (I'll give you the benefit of the doubt)

Thanks... I promise I'm not >__< I'm just having trouble seeing 
what guarantees anyone is getting.



> or if your eyes are glossing over when you get to the important 
> parts of my posts, but in either case I don't feel like 
> repeating myself again. For your benefit, I'm repeating myself 
> as clearly as I can:

Ok thanks for trying again. :)


> Const is basically a view of your data.
> If you have something that's const, it's like looking through a 
> filter that only allows you to do certain things. It is _not_ a 
> guarantee that it's the only view of your data that exists in 
> the universe.

Yup, just like in C++.


> Your code, again, shows that you have two views of your memory. 
> x is a mutable view of your data, and you're mutating it.

Yup, so far so good.


> y is your const view of your data. No matter how hard you try 
> (without casts), you can't mutate y.

Yup.


> You _can_ mutate x, which y is viewing. The y view updates 
> accordingly, but you didn't mutate y.

Yup.


> Maybe in a second you'll say "oh, but that's mutating y" and 
> I'll promptly ignore you completely this time because you've 
> yet again missed the point:2

Nope, not what I said. :)


> You mutated x, not y, y is a view on the same data that x is so 
> mutating x would logically have y's view updated since const 
> isn't a guarantee that you only have one view of the data and 
> thus blah blah blah ... would be my ad infinitum response.

Yes, I already understood this, and I'm pretty sure I still do.




What you're saying, I understand.

What is seems to be missing is the answer to my question:

What _guarantees_ can the compiler make about your code, /based/ 
on the fact that y is a const view, or that the entire struct is 
const?


You keep on telling me that y is a const view, which, obviously, 
it is.

But the question is: why is that useful, compared to C++?

e.g. What kind of a guarantee can a D compiler make about code 
that calls a const method, which a C++ compiler probably wouldn't 
be able to?



> Let me point this out: It's there to give you guarantees and 
> ways to think about your code and to allow you to use the same 
> code for mutable and immutable data. That's it. There's no 
> magic behind it that you're not getting. The idea is that if 
> you want those particular features in your code and you know 
> you can use them effectively, then you use const. Generally, if 
> you want the same code to work on mutable data and immutable 
> data, then you have to use const. It's a bridge that allows the 
> same code to work with either type. You can use this so that 
> you reduce code duplication (and work for you) or/and reduce 
> the amount of instructions loaded in your CPU (potentially 
> reducing the times when your cache is reloaded) or I'm sure 
> there's other good reasons as well, but that's for you to 
> figure out. It isn't a catch all feature. Not everything needs 
> to be bashed with the const golden hammer of doom without any 
> thought behind why you might want it to be const. There's 
> plenty of times where you don't want to use const because it 
> simply doesn't make sense and it doesn't give any additional 
> meaning to your code. But that's okay, you just don't need to 
> use const when it doesn't do anything for you.
>
>
> Your main problem seems to be that you're intentionally trying 
> to break const as hard as you can.


"Hacking around", I guess you could put it. :-D
As well as trying to clarify things for other people who might 
have the same questions as well (which I'm sure they would).

> Obviously, there's nonsensical ways to use const, and I don't 
> think anyone would argue that _any_ feature is completely 
> bulletproof to incompetence. Take classes for instance. Do I 
> really need to give you an example that grossly misuses 
> classes? Does that mean that classes have no purpose? Should I 
> always use structs or parallel arrays because classes can be 
> misused?
> Instead of trying to misuse the feature, you ought to be 
> spending your energy trying to use the feature for your benefit.


It's not a question about misuse, it's a question about 
guarantees. The compiler simply _isn't_ allowed to do something 
that works for 99% of code, while breaking that 1% that misuses 
it (but is legal).

i.e. It's a code generation issue, not a misuse issue.



> (I'm going to make this the last post on the matter ... I'll 
> respond to Mr. Davis' concern on the bug in just a minute, but 
> I've made my full effort to explain const to you and I don't 
> see where additional conversation on my part can clarify this 
> any further.)



Well ok, nice speaking with you then. :)
August 17, 2012
Re: What guarantees does D 'const' provide, compared to C++?
On Friday, 17 August 2012 at 02:49:45 UTC, Jonathan M Davis wrote:
> But take this code for example:
>
> auto i = new int;
> *i = 5;
> const c = i;
> writeln(c);
> func(c); //obviously takes const or it wouldn't compile
> writeln(c);
>
> The compiler _knows_ that c is the same before and after the 
> call to func, because it knows that no other references to that 
> data can exist.


Is there any reason why your example didn't just say

> const(int*) c = null;
> writeln(c);
> func(c);
> writeln(c);


i.e. What was the point of 'i' there?
And why can't a C++ compiler do the same thing?
'c' is a const object, so if C++ code was to modify it, it would 
be undefined behavior, just like in D.
Sorry, I'm a little confused at what you were illustrating here.
1 2 3 4 5 6 7 8
Top | Discussion index | About this forum | D home