May 02, 2012
1. Wouldn't your solution
  (a) Be telling the programmer, "you *can't* lazy-load const objects"?
  (b) Require duplicating the code 3 times? (Yes, you can factor it out as a mixin, but who wants to do that??)

2. "Some folks that like lazy loading such as this seem to have come to the conclusion that they should just pretty much never use const, because it's too restrictive for they want to do."

Yes, that's **exactly** why I've said 'const is broken' for at least a year now, but it seemed like people objected to my conclusion...

The trouble, as I just showed, is that it isn't.
"Lazy-loading" and caching aren't exactly obscure or rarely-used concepts --  which seems to be the way they are portrayed here. They are *bound* to be used in any nontrivial program.
So, if D doesn't let you use those techniques without 'hacking around' the language, then it doesn't matter how awesome D is otherwise -- C++ programmers _simply won't_ switch to D, and other programmers will definitely have trouble using const, immutable, shared, etc...

In other words, my point with this entire thread was:
These issues need to get *fixed* at some point on the _theory_ side. Who cares if the implementation takes an extra year or two to be finished? If it's wrong in theory, it's never going to be right in practice.
And it looks to me like there is no real clean 'fix' for this issue in D... the only solutions are along the lines of using C-style casts in C++ to throw-away const-ness, and we all know that isn't an actual solution...

3. Okay I'll try to avoid resurrecting threads in the future, thanks for letting me know. :) 

May 02, 2012
Also, I think you didn't notice the other problem.

The other problem was with IConnection, whose send() wasn't 'const', which also gives you an error due to the transitivity of const (which I've also claimed is broken).
And how could it? It's just a connection, not a server, so it doesn't parse the input... and it probably changes the state of the connection, since connections often have internal buffers they need to modify (if not prioritization, etc.).

So, what is D's solution for _that_ problem? 

May 02, 2012
On Tuesday, May 01, 2012 20:22:40 Mehrdad wrote:
> 1. Wouldn't your solution
>    (a) Be telling the programmer, "you *can't* lazy-load const objects"?
>    (b) Require duplicating the code 3 times? (Yes, you can factor it out as
> a mixin, but who wants to do that??)
> 
> 2. "Some folks that like lazy loading such as this seem to have come to the conclusion that they should just pretty much never use const, because it's too restrictive for they want to do."
> 
> Yes, that's **exactly** why I've said 'const is broken' for at least a year now, but it seemed like people objected to my conclusion...
> 
> The trouble, as I just showed, is that it isn't.
> "Lazy-loading" and caching aren't exactly obscure or rarely-used concepts --
> which seems to be the way they are portrayed here. They are *bound* to be
> used in any nontrivial program.
> So, if D doesn't let you use those techniques without 'hacking around' the
> language, then it doesn't matter how awesome D is otherwise -- C++
> programmers _simply won't_ switch to D, and other programmers will
> definitely have trouble using const, immutable, shared, etc...
> 
> In other words, my point with this entire thread was:
> These issues need to get *fixed* at some point on the _theory_ side. Who
> cares if the implementation takes an extra year or two to be finished? If
> it's wrong in theory, it's never going to be right in practice.

D's const does exactly what it intends to do. Yes, that means that lazy loading and const are mutually exclusive. And I don't expect that that will ever change. To change it would be to make it so that const isn't guaranteed to be const. There is _zero_ chance of convincing Walter of anything of the sort, and many in the community will back him in that. In order for the compiler to give solid guarantees, it can't be any other way, and more importantly, the fact that we have immutable means that it can't be any other way. If that means that you can't use const in many situations (even if you might use it in those same situations in C++), then that means that you can't use const. D's const is not C++'s const and was never intended to be.

> And it looks to me like there is no real clean 'fix' for this issue in D... the only solutions are along the lines of using C-style casts in C++ to throw-away const-ness, and we all know that isn't an actual solution...

It's worse than not an actual solution. It breaks the type system, throwing away the gurantees that the compiler gives you (easily resulting in bugs if you actually do it) and risks segfaults and the like if the underlying object is actually immutable.

- Jonathan M Davis
May 02, 2012
On Wednesday, 2 May 2012 at 03:22:40 UTC, Mehrdad wrote:
> Yes, that's **exactly** why I've said 'const is broken' for at least a year now, but it seemed like people objected to my conclusion...
>
> The trouble, as I just showed, is that it isn't.
> "Lazy-loading" and caching aren't exactly obscure or rarely-used concepts --  which seems to be the way they are portrayed here. They are *bound* to be used in any nontrivial program.
> So, if D doesn't let you use those techniques without 'hacking around' the language, then it doesn't matter how awesome D is otherwise -- C++ programmers _simply won't_ switch to D, and other programmers will definitely have trouble using const, immutable, shared, etc...

I've never commented on this issue, but here's my viewpoint:

If you intend to change something, it's NOT const. Don't make an object and say you won't change it then change it. It's nonsensical. 9 times out of 10, what you really mean is "I have an object that has some immutable/const data in it".

A clear way to understand what I mean is a Matrix. Some people want "immutable matrices" which cache their determinant when it's time to calculate it. What they REALLY want is a matrix of immutable data. So, instead of a "immutable Matrix!int", they really need to be "Matrix!immutable(int)". Effectively it's the same thing, only it's more precisely defined and it's actually possible to do caching with it.

The way C++ works is simply incorrect, and yes it might take some time to get used to the fact that const means const and immutable means immutable, but if you don't want to respect those types in the first place, there's no sense in using them.
May 02, 2012
Okay, so let's say you're right

   void process1(Student s) { .. }
   void process2(const(Student) s) { ... }

and that what I  guess what I REALLY want is to say, "process1() won't change the student's name, birthday, or any other attribute, but process2() will".

How do you propose I make that guarantee known to the compiler/caller?
Is that not the entire point of saying "const(Student)" in the first place?




"Chris Cain"  wrote in message news:mivrzrerrqlvskxcndva@forum.dlang.org...

On Wednesday, 2 May 2012 at 03:22:40 UTC, Mehrdad wrote:
> Yes, that's **exactly** why I've said 'const is broken' for at least a year now, but it seemed like people objected to my conclusion...
>
> The trouble, as I just showed, is that it isn't.
> "Lazy-loading" and caching aren't exactly obscure or rarely-used concepts --  which seems to be the way they are portrayed here. They are *bound* to be used in any nontrivial program.
> So, if D doesn't let you use those techniques without 'hacking around' the language, then it doesn't matter how awesome D is otherwise -- C++ programmers _simply won't_ switch to D, and other programmers will definitely have trouble using const, immutable, shared, etc...

I've never commented on this issue, but here's my viewpoint:

If you intend to change something, it's NOT const. Don't make an
object and say you won't change it then change it. It's
nonsensical. 9 times out of 10, what you really mean is "I have
an object that has some immutable/const data in it".

A clear way to understand what I mean is a Matrix. Some people
want "immutable matrices" which cache their determinant when it's
time to calculate it. What they REALLY want is a matrix of
immutable data. So, instead of a "immutable Matrix!int", they
really need to be "Matrix!immutable(int)". Effectively it's the
same thing, only it's more precisely defined and it's actually
possible to do caching with it.

The way C++ works is simply incorrect, and yes it might take some
time to get used to the fact that const means const and immutable
means immutable, but if you don't want to respect those types in
the first place, there's no sense in using them. 

May 02, 2012
On Wednesday, 2 May 2012 at 04:05:11 UTC, Mehrdad wrote:
> Okay, so let's say you're right
>
>    void process1(Student s) { .. }
>    void process2(const(Student) s) { ... }
>
> and that what I  guess what I REALLY want is to say, "process1() won't change the student's name, birthday, or any other attribute, but process2() will".
>
> How do you propose I make that guarantee known to the compiler/caller?

What about the object do you want const? How should this object normally change things? It looks like the way you've coded it, your connection will get information off of a server. Does const(Student) mean that it shouldn't write to the server? If so, use something akin to a compile-time dependency injection ... specify that one of those students has a read-only connection. Something like Student!StudentDBConnection might work, and then maybe Student!const(StudentDBConnection).

> Is that not the entire point of saying "const(Student)" in the first place?
"const(Student)" means I won't change _anything_ about the object. It's const. So in a sense, you can say that you won't change the fields name, birthday, etc. That means you can't change the fields.
May 02, 2012
On Tuesday, May 01, 2012 21:05:11 Mehrdad wrote:
> Okay, so let's say you're right
> 
>     void process1(Student s) { .. }
>     void process2(const(Student) s) { ... }
> 
> and that what I  guess what I REALLY want is to say, "process1() won't
> change the student's name, birthday, or any other attribute, but process2()
> will".
> 
> How do you propose I make that guarantee known to the compiler/caller?
> Is that not the entire point of saying "const(Student)" in the first place?

Yes. And if you mark it as const, then the compiler will guarantee it. But with something like lazy loading, the object _does_ change. In D, const actually guarantees that a const object will not be altered, whereas C++'s doesn't. If you have an object which you don't intend to _logically_ alter but which whose state may change due to lazy loading, then the compiler can't give you any real guarantees anyway without having a lazy-loading mechanism of some sort built into the language.

In C++, the compiler can't use it to provide any real guarantees, because the programmer is free to violate const at any time via mutable or casting away const. Walter thinks that this makes C++'s const utterly useless (his focus is very much on what the compiler can and can't guarantee). Most of the rest of us disagree (it _does_ at least stop the programmer from inadvertently mutating a const variable directly), but with Walter's take on it, there's no way that he would have made D's const the same. And C++'s const just doesn't provide the kind of guarantees that D requires anyway, since the fact that a const object could actually be immutable makes it so that you can't safely cast away const to mutate anything, regardless of whether the compiler assumes that const objects never get altered.

The lack of logical const in D can be very annoying for some use cases, but the fact that D's const is guaranteed then makes it much better for other use cases. It's a tradeoff.

If all you want is something which indicates that you don't intend to alter the logical state of a variable (but you may alter its state in other ways - e.g. its cache), then D's compiler can't help you with that. Not even C++'s compiler really does much for that, since its const can be circumvented so easily. It just helps prevent you from doing it accidentally.

- Jonathan M Davis
May 02, 2012
On Wednesday, 2 May 2012 at 04:18:18 UTC, Chris Cain wrote:
> ... specify that one of those students has a read-only connection. Something like Student!StudentDBConnection might work, and then maybe Student!const(StudentDBConnection).

I take the second one back, I've not written any kind of connection code before, but it occurs to me that StudentDBConnection must have some kind of mutable state in order to connect to something.

Maybe a ROConnection object (or a struct and use the awesomeness of D's compile-time duck typing) or something along those lines?
May 02, 2012
"Chris Cain"  wrote in message news:nqgwunggifrgmwwhkcql@forum.dlang.org...
> What about the object do you want const? How should this object normally change things? It looks like the way you've coded it, your connection will get information off of a server.

I don't think you answered my question.

What I said (or meant to ask) was this:
- OK, FINE, let's say I don't know what D's const() means, then. Maybe it isn't suitable for what I need. I just want to know:
 _How do you specify that the function process1() won't modify its 'student' parameter_?

Your response was this:
- "Does const(Student) mean that it shouldn't write to the server?"

To which my answer is:
- I don't know, you tell me. (?) _Should_ I use 'const' to specify this? Or should I use something else?

In other words:
>> Is that not the entire point of saying "const(Student)" in the first place?

You answered that by saying
> "const(Student)" means I won't change _anything_ about the object. It's const. So in a sense, you can say that you won't change the fields name, birthday, etc. That means you can't change the fields.

The problem with your answer is that it implies D DOESN'T SUPPORT O.O.P. with const!!!

If D supported OOP, then why the heck would process1() know (or _care_) how Student works internally?
Why (or how) should it know (or care) that Student uses a database connection?


Wasn't that information an implementation detail?


All process1() needs to know is the *PUBLIC INTERFACE* of Student.
And all it cares to say is: "According to the public interface of Student, none of the methods I will use will modify the object."
process1() has NO IDEA what goes on internally! It has NO IDEA that Student uses a database connection. Maybe it's a network connnection instead. Or maybe it's being unit-tested, and it's actually a dummy object, with no relation to the outside world. Or maybe it's a wrapper/proxy for another object.

The point is: _why should the code for process1() depend on this_?!




So, I'll ask my question again:

How should process1() tell the outside world that it will not be asking its parameter to manipulate itself, WITHOUT breaking the abstraction barrier and 'peeking' into the private world of Student?

May 02, 2012
> In C++, the compiler can't use it to provide any real guarantees, because the programmer is free to violate const at any time via mutable or casting away const.

Maybe I'm being stupid, but how is the case any different in D?