April 02, 2008
On Wed, 02 Apr 2008 16:41:33 +0200, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> "Simen Kjaeraas" wrote
>> On Wed, 02 Apr 2008 16:04:36 +0200, Steven Schveighoffer  wrote:
>>
>>> - a pure method cannot access the mutable portion of a logically
>>> invariant data value.
>>
>> Wouldn't this basically make it transitive invariant?
>
> Yes, which makes my point :)  pure must be transitive, but const / invariant
> by itself does not need to be.
>
> -Steve

So yes, you can do without transitive const, as long as you define logical const as transitive. I can't quite see what point you're trying to make.

-- Simen
April 02, 2008
"Simen Kjaeraas" wrote
> On Wed, 02 Apr 2008 16:41:33 +0200, Steven Schveighoffer  wrote:
>
>> "Simen Kjaeraas" wrote
>>> On Wed, 02 Apr 2008 16:04:36 +0200, Steven Schveighoffer  wrote:
>>>
>>>> - a pure method cannot access the mutable portion of a logically invariant data value.
>>>
>>> Wouldn't this basically make it transitive invariant?
>>
>> Yes, which makes my point :)  pure must be transitive, but const /
>> invariant
>> by itself does not need to be.
>>
>> -Steve
>
> So yes, you can do without transitive const, as long as you define logical const as transitive. I can't quite see what point you're trying to make.

No, I'm not defining logical const as transitive.  I'm defining that pure is transitive.  pure functions have nothing to do with requiring const to be transitive, which is my point.

Did you look at my example in the original post?  What we have now is semantically equivalent to logical const.

-Steve


April 02, 2008
> pure is a tool for multiprogramming.  This allows all the fun stuff that Walter is always talking about.  pure can co-exist with logical const and logical invariant, because if it couldn't, then pure couldn't exist in today's version of const.

Let me expand on this point, because I may not have explained this correctly and as a result, a lot of you are confused at what I'm talking about.

pure functions require transitive invariance.  But this does not mean that an invariant object must be transitively invariant for pure to work.  For a logically invariant object, a pure function will simply not be able to use the mutable portion of that object.

Put another way:  pure requires transitive invariance, but making the keywords invariant and const mean 'transitive' is not *required* for this to happen.  What is required is a well defined const system, where the compiler can tell what is const and what is not const.

The problem with C++'s const and pure is that by default const is not transitive.  Therefore, the compiler has no way of knowing if the developer needs data referenced by const members to be const or not.  If D had this kind of system, then the compiler would have to restrict pure functions to only interact with local value members of a class that did not reference other data.  With const being transitive by default, the compiler can make more assumptions, and have greater assurance that pure has no side effects, but allowing a developer to specify that a piece of a class is not part of the class state does NOT prevent useful pure functions, and does NOT prevent the compiler from enforcing const or pure.  i.e. logical const does not invalidate pure functions and does not prevent multiprogramming as Walter has suggested.

To summarize:  Yes I understand pure functions require transitive invariance.  Yes I understand what logical invariance means.  I have shown that pure functions are still possible alongside logical invariance, as long as the pure function does not use the mutable portion of the class (which is technically not part of the class state anyways).  I have also shown that logical invariance is possible with today's transitive const system, proving that transitive const is semantically equivalent to logical const.

-Steve


April 02, 2008
On 02/04/2008, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>  >>  Clearly, it is
>  >> ALREADY
>  >> POSSIBLE to have logical const

Clearly it isn't.

> > We are suffering from a communications difficulty caused by you and I
>  > using the same phrase ("logical const") to mean entirely different
>  > things. Unless we can agree on a common terminology, we're not going
>  > to be able to get anywhere with this discussion.
>
>
> The communications gap is not in that I do not understand what logical const
>  is.  The communications gap is that you are not understanding that what I
>  have posted is semantically equivalent to logical const.

Look, how about this. How about if, instead of calling such classes "logically const", you instead describe them as "classes whose methods modify global data"? (or "globby" for short). That would keep me happy.

In return, I'll agree to call classes with mutable member variables "classes with mutable member variables". ("muty" for short).

Hopefully, we can then have a conversation without getting confused, or arguing over what words mean.



>  What I am showing
>  is that transitive const is the same as logical const because you can use
>  the always mutable global state as part of the class state.  What this
>  translates to is that logical const is sufficient for multi-programming as
>  long as the correct rules are chosen.

I just don't get what you're saying. It doesn't make sense to me.


>  What I am asking is, because semantically logical const is possible

I don't even know what you mean by that.
April 02, 2008
On 02/04/2008, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> "Janice Caron" wrote
>
> > On 02/04/2008, Steven Schveighoffer wrote:
>  >> "Janice Caron" wrote
>  >>  > pure requires transitive const.
>  >>
>  >>  Forgive me if I don't take your word for it.  Please prove this.
>  >>  Specifically, why pure fails with logical const (not head const as C++
>  >> is).

> I'm assuming you meant f to be part of Stupid?

No, that was just a typo. Or lazy typing - take your pick. I should have written


    not_pure void f(const(Stupid) stupid)
    {
        int t = stupid.y;
        ++stupid.t;
        stupid.y = t;
    }

Try calling f from two threads at the same time, imagine a thread switch partway through f.


>  - a pure method cannot access the mutable portion of a logically invariant
>  data value.

Well, the easy way to do that is to redesign the class into two classes, one const and the other not. That way, you get the exact same benefit, but in addition, you end up saying what you mean, instead of writing obfuscated code.
April 02, 2008
"Janice Caron" wrote
> On 02/04/2008, Steven Schveighoffer wrote:
>> "Janice Caron" wrote
>>
>> > On 02/04/2008, Steven Schveighoffer wrote:
>>  >> "Janice Caron" wrote
>>  >>  > pure requires transitive const.
>>  >>
>>  >>  Forgive me if I don't take your word for it.  Please prove this.
>>  >>  Specifically, why pure fails with logical const (not head const as
>> C++
>>  >> is).
>
>> I'm assuming you meant f to be part of Stupid?
>
> No, that was just a typo. Or lazy typing - take your pick. I should have written
>
>
>    not_pure void f(const(Stupid) stupid)
>    {
>        int t = stupid.y;
>        ++stupid.t;
>        stupid.y = t;
>    }
>

Again, this is not a pure function.  You cannot access the mutable portion of a logically invariant data value.  This does not disprove that logical const can be used alongside pure.

>
>>  - a pure method cannot access the mutable portion of a logically
>> invariant
>>  data value.
>
> Well, the easy way to do that is to redesign the class into two classes, one const and the other not. That way, you get the exact same benefit, but in addition, you end up saying what you mean, instead of writing obfuscated code.

I can ALREADY write "obfuscated" code as you say it.  See my original example.  Supporting logical const directly just makes that easier so I don't have to keep the part of the class that's not part of the state outside the class, and have to "work around" the const system.  Note that none of this violates const or functional programming.

The problem with your solution is that I can't just turn part of a class const, how would one specify that anyways?  I want to just say:

class C{ ??? int mutablePart; int constPart}

C c = new C;
const(C) cc = c; // mutablePart is still mutable

I don't even know how you can do something like this without templates, and then, I am bloating the namespace, and I can't automatically assign one to the other.

-Steve


April 02, 2008
"Janice Caron" wrote
> On 02/04/2008, Steven Schveighoffer wrote:
>> > We are suffering from a communications difficulty caused by you and I
>>  > using the same phrase ("logical const") to mean entirely different
>>  > things. Unless we can agree on a common terminology, we're not going
>>  > to be able to get anywhere with this discussion.
>>
>>
>> The communications gap is not in that I do not understand what logical
>> const
>>  is.  The communications gap is that you are not understanding that what
>> I
>>  have posted is semantically equivalent to logical const.
>
> Look, how about this. How about if, instead of calling such classes "logically const", you instead describe them as "classes whose methods modify global data"? (or "globby" for short). That would keep me happy.
>
> In return, I'll agree to call classes with mutable member variables "classes with mutable member variables". ("muty" for short).
>
> Hopefully, we can then have a conversation without getting confused, or arguing over what words mean.
>

Sure.  Now I'll restate what I have been stating in these terms:  globby classes are EQUIVALENT to logically const classes (or "muty" classes as you call them).  Since they are equivalent, and we can have globby classes today with transitive const, so what is the problem with allowing muty classes? How would this break the const system?

-Steve


April 02, 2008
== Quote from Walter Bright (newshound1@digitalmars.com)'s article
> Don Clugston wrote:
> > As far as I can tell, it's like any optimisation problem -- it's only 5-10% of the code that matters: it's only necessary to use multiple cores efficiently in a small fraction of the code (obviously the entire code needs to be correct). So I'm a little uneasy about arguments for const based on efficiency concerns -- there are many opportunities to worry about stuff which is ultimately irrelevant. I hope that's not happening here.
> Although better code generation is a positive consequence of const, and
> is worth mentioning, it isn't the motivation for it.
> What const and transitive const achieves is more reliable and more
> demonstrably correct code, which will indirectly improve productivity.

I agree that transitive const can achieve more demonstrably correct code
but I don't think it follows that this will necessarily improve productivity.
My experience with const in C++ is that it actually reduces productivity
because I spend more time dealing with the misapplication of const than
I gain from whatever bugs the application of const may have prevented.
In fact, in all my time as a programmer I can't think of a single instance
where I've encountered a bug that could have been prevented through
the use of const.


Sean
April 02, 2008
On 02/04/2008, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> Sure.  Now I'll restate what I have been stating in these terms:  globby
>  classes are EQUIVALENT to logically const classes (or "muty" classes as you
>  call them).  Since they are equivalent, and we can have globby classes today
>  with transitive const, so what is the problem with allowing muty classes?
>  How would this break the const system?

Great! I understood. (I disagree, but I understood).

OK, in what sense are globby classes equivalent to muty classes? Because, you see, I don't think they are. When you modify a global variable, you are modifying something /else/, something other than the class. In no way can this be said to be violating transitive const. But when you modify a mutable variable in C++ (and I have to use C++ as my example, because it's not legal in D), then you /have/ violated transitive const. That difference makes them seem not equivalent to me.
April 02, 2008
"Janice Caron" wrote
> On 02/04/2008, Steven Schveighoffer wrote:
>> Sure.  Now I'll restate what I have been stating in these terms:  globby
>>  classes are EQUIVALENT to logically const classes (or "muty" classes as
>> you
>>  call them).  Since they are equivalent, and we can have globby classes
>> today
>>  with transitive const, so what is the problem with allowing muty
>> classes?
>>  How would this break the const system?
>
> Great! I understood. (I disagree, but I understood).
>
> OK, in what sense are globby classes equivalent to muty classes? Because, you see, I don't think they are. When you modify a global variable, you are modifying something /else/, something other than the class. In no way can this be said to be violating transitive const. But when you modify a mutable variable in C++ (and I have to use C++ as my example, because it's not legal in D), then you /have/ violated transitive const. That difference makes them seem not equivalent to me.

globby classes are equivalent to muty classes because in both cases I am storing information outside the const scope.  In globby classes, I'm storing it in a global AA that has an element for each instance of the class that's created.  In muty classes, I'm storing it in a member variable with the class.  In all cases, it's not considered to be a state of the class, it's just that for muty classes, I'm storing it with the class (and reaping the benefits of not having to manage a globally stored AA).

I can prove that muty classes are equivalent to globby classes:

class muty
{
    mutable X x;
}

is equivalent to
class globby
{
   X x() const {...}
   X x(X newvalue) const {...}
}

Assume the ellipsis' are implementations that get and set a globally (or statically) stored x.

Please don't point out that I can't do the same operations on x in the globby version because it is not a data member, this is a limitation of the D language, and I can always make functions that do the operation needed. The essential proof is that I can re-assign x.

There is no semantic difference.  Both have an x member that is mutable when the instance is const.  The globby version can be supported with today's const regime and compiler, why not also allow the muty version.

As a challenge, come up with a muty type that cannot be implemented as a globby type in the context of constancy/invariance.

-Steve