September 11, 2007
On 9/11/07, Sean Kelly <sean@f4.ca> wrote:
>
> My classic example for the need of "mutable" is a mutex used to synchronize access to class data.  The mutex must be modified even for read operations.


Again, if we let D's "private" attribute also imply C++'s "mutable", then that problem goes away.


September 11, 2007
"Janice Caron" wrote
> What all of these use-cases have in common is the fact that the state is private
>
> Suppose that all class and struct members which were declared private,
> were always mutable,
> even if the class instance is const.

I sort of agree with you, but what about instances where you want derived classes to be able to access the cache?

I think having a keyword for mutable is necessary, but what may make sense is to enforce that only non-public members are allowed to be mutable.

What is the argument against mutable again?

-Steve


September 11, 2007
On 9/11/07, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> "Janice Caron" wrote
> > What all of these use-cases have in common is the fact that the state is private
> >
> > Suppose that all class and struct members which were declared private,
> > were always mutable,
> > even if the class instance is const.
>
> I sort of agree with you,

I believe I can make the case for my argument stronger. In general, when I expose a class's interface, the understood contract is:

 class C
 {
     public:
         /* stuff I want you to know about */

     private:
         /* None of your gorram business. It's PRIVATE.
            You shouldn't care know or care what's in here */
}

To a caller of the code, it should not matter what member functions of C do to its private members, so long as the public interface does what you expect.

Here's another use case. Suppose I start off with a simple class like:

 class C
 {
     void f() { /* do something */ }
 }

 const C c;
 c.f();

But later, as I'm debugging the code, I realise it's not doing quite what I want it to do, and I need to put some diagnostic code in to help me with debugging. So I change it to:

 class C
 {
     void f() { debug ++count; /* do something */ }
     debug private int count;
 }

 const C c;
 c.f();

Whoops! Now it won't compile in debug mode (but it will still compile in release mode). Again, it's because /private/ state is conflicting with the constness.



> but what about instances where you want derived
> classes to be able to access the cache?

I can't think of a use-case for that.

Would it not suffice for the base-class to expose protected functions to provide read-only access to the cache?



> I think having a keyword for mutable is necessary

I believe this thread has shown that there is a need for the /functionality/ that the keyword provides, but I'm not completely convinced that we need the keyword itself. If we allow private data to be implicitly mutable then we don't need the keyword.


> but what may make sense
> is to enforce that only non-public members are allowed to be mutable.

My idea would make that enforcement unnecessary


> What is the argument against mutable again?

In C++, you can do this:

 class C
 {
 public:
     mutable int x;
     C() { x = 0; }
     void f() const { x = 5; }
 }

 main()
 {
     const C c;
     printf("%d\n", c.x); /* prints 0; */
     c.f();
     printf("%d\n", c.x); /* prints 5; */
 }

This is clearly nonsense.

That would be disallowed in my scheme. (...at least, if main() was in
a different file from the definition of C).
September 11, 2007
"Janice Caron" wrote
> On 9/11/07, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>> "Janice Caron" wrote
>> > What all of these use-cases have in common is the fact that the state
>> > is
>> > private
>> >
>> > Suppose that all class and struct members which were declared private,
>> > were always mutable,
>> > even if the class instance is const.
>>
>> I sort of agree with you,
>
> I believe I can make the case for my argument stronger. In general, when I expose a class's interface, the understood contract is:
>
> class C
> {
>     public:
>         /* stuff I want you to know about */
>
>     private:
>         /* None of your gorram business. It's PRIVATE.
>            You shouldn't care know or care what's in here */
> }

Yeah, I understand your original point.  I'm not disputing that, which is why I "sort of" agree with you.  My point that protected should be able to be mutable as well as private was the point I was trying to make.

>> but what about instances where you want derived
>> classes to be able to access the cache?
>
> I can't think of a use-case for that.

The one that comes to mind is if you wanted to slightly modify the way a cache was used.  The two options are: make the cache protected, and allow derived classes to use it (in which case mutable is required), or re-implement the cache in the slightly modified way in the derived class, in which case you are carrying around 2 caches for no reason.

> Would it not suffice for the base-class to expose protected functions to provide read-only access to the cache?

Well, yeah, you could do it that way, but you would have to know before-hand how your cache was going to be accessed/used by the derived classes, therefore restricting the creativity of the author of the derived class.

>> What is the argument against mutable again?
>
> In C++, you can do this:
>
> class C
> {
> public:
>     mutable int x;
>     C() { x = 0; }
>     void f() const { x = 5; }
> }
>
> main()
> {
>     const C c;
>     printf("%d\n", c.x); /* prints 0; */
>     c.f();
>     printf("%d\n", c.x); /* prints 5; */
> }
>
> This is clearly nonsense.
>
// tango style
class NonsenseInD
{
  private int _x = 0;
  int x() const { return _x;}
  void f() const { x = 5;}
}

// could be in another file
int main(char[][] args)
{
  const NonsenseInD c = new NonsenseInD;
  Stdout(c.x).newline; // prints 0;
  c.f();
  Stdout(c.x).newline; // prints 5;
}

Even with this example, I still don't see why mutable is such a horrible thing...  To me it makes sense to have pieces of a class that can change, even when the class is const.  You have given several good examples (files, net connections, etc), but I think your idea of enforcing public data being const is probably not feasible.

-Steve


September 11, 2007
On 9/11/07, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> // tango style
> class NonsenseInD
> {
>   private int _x = 0;
>   int x() const { return _x;}
>   void f() const { x = 5;}
> }
>
> // could be in another file
> int main(char[][] args)
> {
>   const NonsenseInD c = new NonsenseInD;
>   Stdout(c.x).newline; // prints 0;

No it won't, because it won't compile, because x is private.

(It will compile if main is in the same file as class NonsenseInD, but
I can live with that).
September 11, 2007
> No it won't, because it won't compile, because x is private.

Sorry - accept my apologies - I misread your code.
September 11, 2007
Steven Schveighoffer wrote:
> "Janice Caron" wrote
>> On 9/11/07, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>>> but what about instances where you want derived
>>> classes to be able to access the cache?
>> I can't think of a use-case for that.
> 
> The one that comes to mind is if you wanted to slightly modify the way a cache was used.  The two options are: make the cache protected, and allow derived classes to use it (in which case mutable is required), or re-implement the cache in the slightly modified way in the derived class, in which case you are carrying around 2 caches for no reason.

Provide a property to access the cache. It'll likely be inlined, so no performance hit.

September 11, 2007
Janice Caron wrote:
> On 9/11/07, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>> What is the argument against mutable again?
> 
> In C++, you can do this:
> 
>  class C
>  {
>  public:
>      mutable int x;
>      C() { x = 0; }
>      void f() const { x = 5; }
>  }
> 
>  main()
>  {
>      const C c;
>      printf("%d\n", c.x); /* prints 0; */
>      c.f();
>      printf("%d\n", c.x); /* prints 5; */
>  }
> 
> This is clearly nonsense.
> 
> That would be disallowed in my scheme. (...at least, if main() was in
> a different file from the definition of C).

And why is this nonsense?? Because x is public? I don't see the problem here.

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
September 11, 2007
Sean Kelly wrote:
> read operations.  But for better or worse, D const has a different aim.  The goal is largely to produce a system which allows for compiler optimization rather than to enforce some sort of logical restrictions on behavior.  I suspect this means that D apps won't look very much like C++ apps in terms of how const is used, and the overall utility for the average programmer may well be somewhat small.
> 
> 
> Sean

I'm don't think that's entirely true. 'invariant' the keyword is indeed made to allow several compiler and program optimizations, but 'const' the keyword is really for enforcing program contracts and restrictions, thus improving safety. I don't even think 'const' the keyword has any use whatsoever for optimization.


-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
September 11, 2007
> And why is this nonsense?? Because x is public? I don't see the problem here.

What's the use-case for mutable non-private members?

I would say that it's nonsense if there's no need for them.

"Nonsense" may be the wrong word. "Should not be part of D" is more what I really mean.