www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - const(FAQ)

reply Walter Bright <newshound1 digitalmars.com> writes:
The same questions about const come up repeatedly, so I decided that it 
was past time to put up a FAQ dedicated to const. The initial version is 
far from complete, but it's a start.

http://www.digitalmars.com/d/2.0/const-faq.html
Mar 28 2008
next sibling parent reply Gregor Richards <Richards codu.org> writes:
Walter Bright wrote:
 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

But the FAQ is const, so you can't write new entries :( - Gregor Richards P.S. :P
Mar 28 2008
parent reply janderson <askme me.com> writes:
Gregor Richards wrote:
 Walter Bright wrote:
 The same questions about const come up repeatedly, so I decided that 
 it was past time to put up a FAQ dedicated to const. The initial 
 version is far from complete, but it's a start.

 http://www.digitalmars.com/d/2.0/const-faq.html

But the FAQ is const, so you can't write new entries :( - Gregor Richards P.S. :P

LOL. Seriously though, you could on the "comments" page. -Joel
Mar 28 2008
parent reply "Craig Black" <craigblack2 cox.net> writes:
"janderson" <askme me.com> wrote in message 
news:fskhgv$e31$1 digitalmars.com...
 Gregor Richards wrote:
 Walter Bright wrote:
 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.

 http://www.digitalmars.com/d/2.0/const-faq.html

But the FAQ is const, so you can't write new entries :( - Gregor Richards P.S. :P

LOL. Seriously though, you could on the "comments" page. -Joel

Nope, because D const is transitive, so the comments page is const as well.
Mar 28 2008
parent Walter Bright <newshound1 digitalmars.com> writes:
Craig Black wrote:
 "janderson" <askme me.com> wrote in message 
 news:fskhgv$e31$1 digitalmars.com...
 Gregor Richards wrote:
 But the FAQ is const, so you can't write new entries :(



Since it's const, another user could change it.
Mar 29 2008
prev sibling next sibling parent reply Jacob Carlborg <doobnet gmail.com> writes:
Walter Bright wrote:
 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

Very nice. But you need to update the D 2.0 main page also so people actually can find it.
Mar 28 2008
parent Extrawurst <spam extrawurst.org> writes:
Jacob Carlborg schrieb:
 Very nice. But you need to update the D 2.0 main page also so people 
 actually can find it.

while at it u could add the SafeD article to the main page too ;)
Mar 28 2008
prev sibling next sibling parent reply Jason House <jason.james.house gmail.com> writes:
Walter Bright wrote:

 The same questions about const come up repeatedly, so I decided that it
 was past time to put up a FAQ dedicated to const. The initial version is
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

It's good to see this :) I think it needs something on enums for manifest constants.
Mar 28 2008
parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Jason House wrote:
 Walter Bright wrote:
 
 The same questions about const come up repeatedly, so I decided that it
 was past time to put up a FAQ dedicated to const. The initial version is
 far from complete, but it's a start.

 http://www.digitalmars.com/d/2.0/const-faq.html

It's good to see this :) I think it needs something on enums for manifest constants.

Agreed, and also explain why invariant(int) x = 5; Still reserves 4 bytes of space for an int.
Apr 01 2008
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 01 Apr 2008 00:20:20 -0700, Robert Fraser wrote:

 explain why
 
 invariant(int) x = 5;
 
 Still reserves 4 bytes of space for an int.

So you can take the address of it?? -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Apr 01 2008
parent Robert Fraser <fraserofthenight gmail.com> writes:
Derek Parnell wrote:
 On Tue, 01 Apr 2008 00:20:20 -0700, Robert Fraser wrote:
 
 explain why

 invariant(int) x = 5;

 Still reserves 4 bytes of space for an int.

So you can take the address of it??

Right, but that should be in the FAQ.
Apr 01 2008
prev sibling next sibling parent reply "Unknown W. Brackets" <unknown simplemachines.org> writes:
Question:

In my limited use of const thus far, I've found that "ignoring" or "just 
not using" it is not as possible as suggested.  This is because the 
standard library imposes it.

Or, in other words, if I ignore const and pretend it doesn't exist, 
Phobos will wake me up from my sleep whenever I use a function that, 
e.g. returns a string.

I may be mistaken but this has been my experience.  Not that I don't 
want to use const, necessarily.

-[Unknown]


Walter Bright wrote:
 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

Mar 28 2008
next sibling parent reply serg kovrov <sergk mailinator.com> writes:
Unknown W. Brackets wrote:
 Question:
 
 In my limited use of const thus far, I've found that "ignoring" or "just 
 not using" it is not as possible as suggested.  This is because the 
 standard library imposes it.
 
 Or, in other words, if I ignore const and pretend it doesn't exist, 
 Phobos will wake me up from my sleep whenever I use a function that, 
 e.g. returns a string.
 
 I may be mistaken but this has been my experience.  Not that I don't 
 want to use const, necessarily.
 
 -[Unknown]

This is my experience so far as well. It's a shame, whenever I try D2 (I usually do once in couple months, after seeing "most of the issues are fixed now"), I always fall back to D1 after coule of hours figuring what I have to do (cast/dup to and when) to achieve the task at hand. Either it is me too dumb to grok it, or const system is not intuitive(prodictive) yet. And productiveness (applied to me) is what I look for in first place. -- serg.
Mar 29 2008
parent Derek Parnell <derek psych.ward> writes:
On Sun, 30 Mar 2008 02:42:25 +0200, serg kovrov wrote:

 Unknown W. Brackets wrote:
 Question:
 
 In my limited use of const thus far, I've found that "ignoring" or "just 
 not using" it is not as possible as suggested.  This is because the 
 standard library imposes it.


Yes it does, but that hasn't been a problem. In fact, it has been a problem in those few times that phobos doesn't use string.
 I always fall back to D1 after coule of hours figuring what 
 I have to do (cast/dup to and when) to achieve the task at hand.

This *is* wierd. I'm using D2 as my version-of-choice an I almost never have to cast or dup. In fact, I haven't needed to cast at all and the only dups I need are when I'm returing a slice to a caller who is going to later manipulate the data in the slice. Even then, it guess I should still return an invariant and get the caller to do the dup if they need to. But the D2 const system is not impeding me at all ... well I did have to work around the absence of tail-const once. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Mar 29 2008
prev sibling parent Regan Heath <regan netmail.co.nz> writes:
Unknown W. Brackets wrote:
 In my limited use of const thus far, I've found that "ignoring" or "just 
 not using" it is not as possible as suggested.  This is because the 
 standard library imposes it.
 
 Or, in other words, if I ignore const and pretend it doesn't exist, 
 Phobos will wake me up from my sleep whenever I use a function that, 
 e.g. returns a string.

The return-type-has-const-of-parameter feature/idea should hopefully resolve this, as in, if you call split on a mutable string you get mutable slices, if you call it on an immutable string you get immutable slices. Regan
Mar 31 2008
prev sibling next sibling parent reply janderson <askme me.com> writes:
Walter Bright wrote:
 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

I apologize if this was already suggested but that last section "Why aren't function parameters const by default" got me thinking. What if you could surround code in a const block: const { //Anything in here gets const by default void foo(int* p) {} }; Ok, this maybe something to add later when the current const is stable. -Joel
Mar 28 2008
parent Walter Bright <newshound1 digitalmars.com> writes:
janderson wrote:
 I apologize if this was already suggested but that last section "Why 
 aren't function parameters const by default" got me thinking.  What if 
 you could surround code in a const block:
 
 const
 {
    //Anything in here gets const by default
     void foo(int* p) {}
 };

It already means something else: const void foo(int* p) {}
Mar 28 2008
prev sibling next sibling parent reply guslay <guslay gmail.com> writes:
Walter Bright Wrote:

 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

From my experience, the need for logical constness is a rare occurrence, but it invariably happens as projects that adhere to a const regime grow. With the const system in D offering must stronger guarantees than in C++ (which is a good thing), the need for logical const is even larger. I have a hard time figuring how const-correctness can work for large projects (which is one thing D const is intended to help) without that flexibility. - Could you elaborate more on what mutable members would break/prevent, if used reasonably? - If I do need mutable members in a const method (for lazy evaluation, caching, counter), what should I do? Is there technique you can propose to escape it (e.g. a way I can externalize the mutable part (seems difficult because of the transitive nature of const) )?
Mar 28 2008
next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
guslay wrote:
 - Could you elaborate more on what mutable members would
 break/prevent, if used reasonably?

"reasonably" is not a factor. The point of compiler enforcement is you won't be relying on whether programmers are reasonable or not - it offers a guarantee.
 - If I do need mutable members in a const method (for lazy
 evaluation, caching, counter), what should I do? Is there technique
 you can propose to escape it (e.g. a way I can externalize the
 mutable part (seems difficult because of the transitive nature of
 const) )?

It can't be done with transitive const. My suggestion for such things is to use private data members, and read the values with property functions.
Mar 28 2008
prev sibling next sibling parent reply Kevin Bealer <kevinbealer gmail.com> writes:
guslay Wrote:

 Walter Bright Wrote:
 
 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

From my experience, the need for logical constness is a rare occurrence, but it invariably happens as projects that adhere to a const regime grow. With the const system in D offering must stronger guarantees than in C++ (which is a good thing), the need for logical const is even larger.

Since D const has different effects, the places where it is needed will be different and I think fewer, simply because the places where it is useful are (intentionally) fewer. Namely, it is no longer useful for logical const. The times that I can remember using logical const in C++ have usually been for "compatibility" reasons, i.e. there is an interface and the method is defined something like "int foo(...) const = 0;", or backward compatibility such as when "lazy" evaluation is added to a class. Was const a need or a premature optimization? When is there a case where logical const actually provides benefits over leaving the methods non-const? I would suggest that in many cases, D interfaces should avoid const since you can't know if lazy evaluation and similar are needed. Using const here is a case of overspecifying, like an interface that takes a reference to a "StudentCheckingAccount" object but only uses methods from the parent interface "CheckingAccount" or grandparent "Account" object (assume an inheritance hierarchy following the names.) Demanding that a concrete class be const is a larger burden than in C++ since there is no workaround.
 I have a hard time figuring how const-correctness can work for large 
 projects (which is one thing D const is intended to help) without that 
 flexibility.

I think just by not putting "const" on the logically const stuff. This impacts other methods that call those methods -- but the calling methods are actually "logically" const themselves, by virtue of calling logically const stuff, so they are supposed to be affected. D const is a different tool than C++ const. In K&R C, you can define a method like "int foo()" and decide later that you are going to send (and receive) arguments anyway -- in C++ this possibility is lost. In C++ you can define a method as const, but later on decide that it isn't really "bitwise" const. In D you can't -- const has been given "teeth" by D, just like function signatures were given "teeth" by C++.
 - Could you elaborate more on what mutable members would 
 break/prevent, if used reasonably?

The idea is that "const" in D means that the compiler can guarantee that no side effects happen. First, if you call a method several times, can the compiler eliminate the subsequent calls? for(int i = 0; i != v.size(); i++) cout << v[i]; The compiler has to call v.size() for every iteration in C++. In this case, if both v.operator[](int) and v.size() are inlined and simple then the compiler (might) be able to check constness via data flow analysis. But if not, the compiler can't cache .size() because in C++ the const might be "logical". More importantly, it goes back to the idea of "reentrant" code. Locks exist to prevent race conditions -- which are due to side effects. Thus, side effect free ("pure") functions can be called by multiple threads at the same time with no locking, and causing no possible problem, since the calls are guaranteed to have no effects. But that's not the case for "logical" const, so in C++ "const" is useless for making this determination. In D const is about guarantees regarding bits, bytes, synchronization, and side effects, whereas in C++ version is about telling another programmer that the object has "the same value" before and after a method call. Both goals are useful to some degree, but Walter is betting (as I read it), that in the future, guarantees about side effects and so on are much more useful, especially when code is scaled up and threaded.
 - If I do need mutable members in a const method (for lazy evaluation, 
 caching, counter), what should I do? Is there technique you can 
 propose to escape it (e.g. a way I can externalize the mutable part 
 (seems difficult because of the transitive nature of const) )?

Yes -- any data stored outside the class can be fiddled with. int * GetValue(inout int key) { static int serial = 1; static int[int] map; if (key == -1) { key = ++ serial; map[key] = 0; } return key in map; } class SomeClass { public: int serial = -1; int counter() const { int * p = GetValue(serial); return ++*p; } }; (There might be much simpler ways but I think this should work regardless of const semantics really, since const applies only to data within the object itself... I haven't tried it though.) Kevin
Mar 29 2008
next sibling parent reply Kevin Bealer <kevinbealer gmail.com> writes:
Kevin Bealer Wrote:

# int * GetValue(int key)
# {
#     int * p = (key in map);
#     if (p is null) {
#         map[key] = 0;
#         p = key in map;
#     }
#     return p;
# }
 
 class SomeClass {
 public:
     int serial = -1;
     static int nextSerial = 1;

# this() { # serial = ++nextSerial; # }
     
     int counter() const
     {
         int * p = GetValue(serial);
         return ++*p;
     }
 };
 

[ Okay, I've fixed this a bit since it was clearly flawed, lines starting with # have changed. ] Kevin
Mar 29 2008
parent reply "Koroskin Denis" <2korden+D gmail.com> writes:
Slightly modifying your example...

Looks like a bug to me:

import std.stdio;

void set(inout int key, int value)
{
     key =3D value;
}

class Square {
     private int _area =3D -1;
     private int _width =3D 0;

     public this(int width)
     {
         _width =3D width;
     }

     public const int area()
     {
         if (_area =3D=3D -1) {
             //_area =3D _width*_width;      // we cannot change variabl=
e  =

value direcly
             set(_area, _width*_width);    // but we can do it _indirect=
ly_  =

???
                                           // it means that _all_ variab=
les  =

are mutable!
         }
         return _area;
     }
}

int main(string[] args)
{
     const Square c =3D new Square(10);
     writefln(c.area());

     return 0;
}
Mar 29 2008
parent Kevin Bealer <kevinbealer gmail.com> writes:
Koroskin Denis Wrote:

 Slightly modifying your example...
 
 Looks like a bug to me:
 
 import std.stdio;
 
 void set(inout int key, int value)
 {
      key = value;
 }
 
 class Square {
      private int _area = -1;
      private int _width = 0;
 
      public this(int width)
      {
          _width = width;
      }
 
      public const int area()
      {
          if (_area == -1) {
              //_area = _width*_width;      // we cannot change variable  
 value direcly
              set(_area, _width*_width);    // but we can do it _indirectly_  
 ???
                                            // it means that _all_ variables  
 are mutable!
          }
          return _area;
      }
 }
 
 int main(string[] args)
 {
      const Square c = new Square(10);
      writefln(c.area());
 
      return 0;
 }

Maybe I'm missing something but checking your code in the version of dmd that I currently have (2.007), the compiler says: Error: cast(int)(this._area) is not an lvalue Kevin
Mar 29 2008
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Kevin Bealer wrote:
 Both goals are useful to some degree, but Walter is betting (as I
 read it), that in the future, guarantees about side effects and so on
 are much more useful, especially when code is scaled up and threaded.

Yes, your interpretation is correct. I think that being able to mathematically (and mechanically) prove things about a program will be increasingly valuable.
Mar 29 2008
prev sibling parent reply guslay <guslay gmail.com> writes:
Kevin Bealer Wrote:

 guslay Wrote:
 
 
 The times that I can remember using logical const in C++ have usually been for
"compatibility" reasons, i.e. there is an interface and the method is defined
something like "int foo(...) const = 0;", or backward compatibility such as
when "lazy" evaluation is added to a class.  Was const a  need or a premature
optimization?  When is there a case where logical const actually provides
benefits over leaving the methods non-const?
 
 I would suggest that in many cases, D interfaces should avoid const since you
can't know if lazy evaluation and similar are needed.  Using const here is a
case of overspecifying, like an interface that takes a reference to a
"StudentCheckingAccount" object but only uses methods from the parent interface
"CheckingAccount" or grandparent "Account" object (assume an inheritance
hierarchy following the names.)  Demanding that a concrete class be const is a
larger burden than in C++ since there is no workaround.

That's why I feel that this is the biggest threat to the adaption of a const-correctness policy in large D programs. You are basically saying don't use const unless you know all the implementation details about a class, and don't put const in Interface/abstract class, just in final concrete class. As you point, casting away constness is not an option. You need a way out, otherwise const will just be used for trivial things.
 
 - Could you elaborate more on what mutable members would 
 break/prevent, if used reasonably?

The idea is that "const" in D means that the compiler can guarantee that no side effects happen. First, if you call a method several times, can the compiler eliminate the subsequent calls? for(int i = 0; i != v.size(); i++) cout << v[i]; The compiler has to call v.size() for every iteration in C++. In this case, if both v.operator[](int) and v.size() are inlined and simple then the compiler (might) be able to check constness via data flow analysis. But if not, the compiler can't cache .size() because in C++ the const might be "logical".

Logical const is still const, as far has there is no visible (public) side effect on the object. The implementation is still bound to that contract. The result of .size() may still be cached.
 
 More importantly, it goes back to the idea of "reentrant" code.  Locks exist
to prevent race conditions -- which are due to side effects.  Thus, side effect
free ("pure") functions can be called by multiple threads at the same time with
no locking, and causing no possible problem, since the calls are guaranteed to
have no effects.  But that's not the case for "logical" const, so in C++
"const" is useless for making this determination.
 
 In D const is about guarantees regarding bits, bytes, synchronization, and
side effects, whereas in C++ version is about telling another programmer that
the object has "the same value" before and after a method call.
 
 Both goals are useful to some degree, but Walter is betting (as I read it),
that in the future, guarantees about side effects and so on are much more
useful, especially when code is scaled up and threaded.
 
 - If I do need mutable members in a const method (for lazy evaluation, 
 caching, counter), what should I do? Is there technique you can 
 propose to escape it (e.g. a way I can externalize the mutable part 
 (seems difficult because of the transitive nature of const) )?

Yes -- any data stored outside the class can be fiddled with. int * GetValue(inout int key) { static int serial = 1; static int[int] map; if (key == -1) { key = ++ serial; map[key] = 0; } return key in map; } class SomeClass { public: int serial = -1; int counter() const { int * p = GetValue(serial); return ++*p; } }; Kevin

So, there a way around it. You can outsource the mutable part to a static/global. This is a side effect. Why not allow a mutable private members, and keep those implementation details encapsulated within the class. This code is not more guaranteed to be "reentrant" that mutable one. With const, you promise that the object that will exhibit to the outside world a const behavior. However, you cannot say that a const-call has no side effect at all. In other words, const does not mean pure, with or without mutable members.
Mar 29 2008
parent reply Kevin Bealer <kevinbealer gmail.com> writes:
guslay Wrote:

 Kevin Bealer Wrote:
 
 guslay Wrote:
 
 
 I would suggest that in many cases, D interfaces should avoid const since you
can't know if lazy evaluation and similar are needed.  Using const here is a
case of overspecifying, like an interface that takes a reference to a
"StudentCheckingAccount" object but only uses methods from the parent interface
"CheckingAccount" or grandparent "Account" object (assume an inheritance
hierarchy following the names.)  Demanding that a concrete class be const is a
larger burden than in C++ since there is no workaround.

That's why I feel that this is the biggest threat to the adaption of a const-correctness policy in large D programs. You are basically saying don't use const unless you know all the implementation details about a class, and don't put const in Interface/abstract class, just in final concrete class.

Yes and no. You can make the interface methods const but not do lazy evaluation later, or you can make them non-const and leave the door open. But you have to decide. You can change the decision later but its like any const-correctness-scheme change, it can potentially bubble up the code dependency tree. A lot of C++ programmers seem to follow a concept that everything should be const all the time unless there is a reason not to. In the D const world, the cost of const is higher so you really have to ask the cost/benefit question -- does this buy me anything -- when applying const. For interfaces and base classes, this answer will be no more often than for concrete classes.
 As you point, casting away constness is not an option. You need a way out,
otherwise const will just be used for trivial things.

In C++, const is about observable values via a human-understood subset of the public interface (e.g. if a method changes a string's capacity() but not its size or data, is it still logically const?). In some cases, it seems like const only applies to an object's position in a sort order. It's like advisory locking in unix. In D it is about reentrant safety and bits. The C++ version is more useful as a guideline for communication between programmers, but the D version is more useful as a guarantee about code behavior.
 - Could you elaborate more on what mutable members would 
 break/prevent, if used reasonably?

The idea is that "const" in D means that the compiler can guarantee that no side effects happen. First, if you call a method several times, can the compiler eliminate the subsequent calls? for(int i = 0; i != v.size(); i++) cout << v[i]; The compiler has to call v.size() for every iteration in C++. In this case, if both v.operator[](int) and v.size() are inlined and simple then the compiler (might) be able to check constness via data flow analysis. But if not, the compiler can't cache .size() because in C++ the const might be "logical".

Logical const is still const, as far has there is no visible (public) side effect on the object. The implementation is still bound to that contract. The result of .size() may still be cached.

Assuming the person writing the code made sure of this... But once you have mutable members, the compiler cannot rely on the value of size() changing or not, it becomes a human decision. Is the value of vector.capacity() allowed to change? From the point of view of the "value" of the vector, yes. From a compiler/optimization point of view, no. To some extent, this could actually be fixed in C++ simply by the standards committee saying that its okay for a compiler to rely on repeatability of method return values and to omit duplicate calls to methods.
 So, there a way around it. You can outsource the mutable part to a
static/global.
 
 This is a side effect. Why not allow a mutable private members, and keep those
implementation details encapsulated within the class. This code is not more
guaranteed to be "reentrant" that mutable one.
 
 With const, you promise that the object that will exhibit to the outside world
a const behavior. However, you cannot say that a const-call has no side effect
at all. 
 
 In other words, const does not mean pure, with or without mutable members.

You're right - the definition of "pure" in this sense is much stronger than "const", so I overstepped here. In this case "const" is not "pure" but is kind of like "pure" relative to the object in question, so some of the optimization might not be as possible unless all behaviors of the method are "read" rather than "write", not just those affecting internal state of this object. But the "pure" keyword is reserved, so maybe we'll see that as well. Kevin
Mar 29 2008
parent guslay <guslay gmail.com> writes:
Kevin Bealer Wrote:

 guslay Wrote
 ... logical const ...

I still don't see how dividing a const composite object (ie a class) in two separate parts (mutable and immutable) would prevent any optimization or thwart future development. I can see the optimization benefit of an eventual pure qualifier. With no possible side effects, it would allow crazy functional programming tricks (reordering, parallel dispatch, memoizing). But const (or invariant) doesn't mean pure. The following does compile, and is bitwise const. It's legal and it's full of side effects. static int dim = 0; class Vector { public const int size() { return ++.dim; } public const void printElement( int i ) { // print element i to stdout } }; As opposed to pure function, the only "mathematical" guarantee that the const qualifiers gives on a method is that its immutable bits will not be modified. Nothing else. So what is the problem if I say that only half the bits are immutable? Const/invariant on data enables aggressive optimizations; const/invariant on a method does not. Or am I missing something?
Mar 29 2008
prev sibling parent "Koroskin Denis" <2korden gmail.com> writes:
On Sat, 29 Mar 2008 21:03:35 +0300, Kevin Bealer <kevinbealer gmail.com>  
wrote:

 Maybe I'm missing something but checking your code in the version of dmd  
 that I currently have (2.007), the compiler says:

 Error: cast(int)(this._area) is not an lvalue

 Kevin

DMD 2.012 compiles the code without a single warning.
Mar 29 2008
prev sibling next sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Walter Bright, el 28 de marzo a las 15:33 me escribiste:
 The same questions about const come up repeatedly, so I decided that it was
past time to put up a FAQ dedicated to const. The initial version is far from 
 complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

About "Why aren't function parameters const by default?": Why aren't *all* variables const by default? It was discussed a long time ago and AFAIK most people liked it. And about "Why not use readonly to mean read only view?": Why not use view to mean read only view? As discussed recently? I don't think "because it's not that clear that 'view' means 'read only view'" is a good enough reason for changing the const meaning to make it mean 'read only view'. If words are arbitrary, at least this scheme let you keep the old const meaning... -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Breathe, breathe in the air. Don't be afraid to care. Leave but don't leave me. Look around and choose your own ground.
Mar 28 2008
parent Walter Bright <newshound1 digitalmars.com> writes:
Leandro Lucarella wrote:
 Walter Bright, el 28 de marzo a las 15:33 me escribiste:
 The same questions about const come up repeatedly, so I decided that it was
past time to put up a FAQ dedicated to const. The initial version is far from 
 complete, but it's a start.

 http://www.digitalmars.com/d/2.0/const-faq.html

About "Why aren't function parameters const by default?": Why aren't *all* variables const by default?

Because you'd have to throw out half of the existing D code base. It also doesn't buy you that much, after all, it isn't hard to get into the habit of: const x = 3; rather than: int x = 3;
 It was discussed a long time ago and AFAIK most people liked it.
 
 And about "Why not use readonly to mean read only view?":
 
 Why not use view to mean read only view?
 
 As discussed recently? I don't think "because it's not that clear that
 'view' means 'read only view'" is a good enough reason for changing the
 const meaning to make it mean 'read only view'. If words are arbitrary, at
 least this scheme let you keep the old const meaning...

The D 1.0 const was just a storage class, not a type modifier. It still is a storage class, and: const int x = 3; still work with 1.0 and 2.0.
Mar 29 2008
prev sibling next sibling parent Davidson Corry <davidsoncorry comcast.net> writes:
Walter Bright wrote:
 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

Thank you! Very informative. ------------ I would find very helpful some further discussion of your thoughts on why const and invariant are crucial to multiprogramming. I sense that you are correct, but the details are yet murky to me. I mentioned, over in the "const debacle' thread, that const on a parameter could be considered as part of the method's contract. And guslay, in this thread, noted the same thing:
 Logical const is still const, as far has there is no visible (public)
 side effect on the object. The implementation is still bound to that
 contract. The result of .size() may still be cached.

That is, in some sense foo(const(X) x) carries with it the (implied or express) postcondition out { x == old.x; } which reads as "x looks just like it did when we got it". On further thought, I realize that this is not strictly true. That is, it is true ONLY in the degenerate case of single-threaded execution: contracts (in Eiffel and D) allow the method to violate the class invariant "in the interim" -- that is, while executing private code, including private calls to subfunctions -- so long as the invariant is re-established at the time of the method return. Likewise, the postcondition doesn't have to be established until the method returns. In single-threaded code, this much more limited guarantee is equivalent to "I'm not changing x anywhere in the middle", because there IS no one else using x while I've got control of it. But with multiprogramming, that's no longer true. The contract metaphor is no longer accurate. The problems -- one for language designers, a different one for language users -- is that the "degenerate" case of single-threading IS 98% OF THE CODING WE DO, without even thinking about it. Pretty much all programming languages I know of have, built into their syntax**, the assumption that nothing else is happening but what they are doing: void foo() { some_statement; <--- what is happening here? some_other_statement; } some_other_statement depends on the assumption that whatever some_statement did, nothing that it did has changed by the time some_other_statement gets control. And I don't see how it could be otherwise. For that matter, HUMAN languages all make the same assumption. When I ask, "How about them 'Blazers, guy?" I do not consider the price of first-quality saffron in Parma, even though that was going on, too. And if I put my lunch sack in the fridge at work and mark it 'const' (as in, "Please don't take my lunch"), that does not guarantee that Ralphie The Sandwich Pilferer isn't going to violate that "contract". In human affairs, these things are handled by (at least) one of two methods: convention (social contract), or active intervention by someone named "manager" or "coordinator" (or in Ralphie's case, "hit man"...). These are analogous to "language feature" and "runtime code including library support", I believe. In human affairs, the agents on the ground, the line workers, are the ones "who do the real work"... but without inserting the third-party manager AND GIVING UP SOME AUTONOMY to her (or to the "virtual" manager of convention), NOTHING OF SIGNIFICANT SCALE GETS DONE. I suspect that the analogy extends to coding. And I do not think that we have yet invented a workable (much less an elegant) syntax for relinquishing autonomy in programming. ** Some programming languages have added syntax features like 'lock', 'synchronized' and 'separate' to support multiprogramming. I think it's clear they don't go far enough, yet. Likewise, I sense that 'const' and 'invariant' will be fundamental here -- not sufficient, but necessary. I'm looking forward to seeing it all evolve. Maybe even contributing a chromosome or two... -- Dai p.s. I note that the "social contract" bit applies to programming as well. D syntax can only protect you against other programs WRITTEN IN D, not against rm -rf *. And I'm not aware of any syntax constructs that can prevent my wife from hitting the power button before clicking "save"... and then blaming me for her work getting lost. <grin>
Mar 29 2008
prev sibling parent reply Regan Heath <regan netmail.co.nz> writes:
Walter Bright wrote:
 The same questions about const come up repeatedly, so I decided that it 
 was past time to put up a FAQ dedicated to const. The initial version is 
 far from complete, but it's a start.
 
 http://www.digitalmars.com/d/2.0/const-faq.html

Typo "Jave" in "It would be a huge break from past D practice, and practice in C, C++, Jave, C#, etc." Regan
Mar 31 2008
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Regan Heath wrote:
 Typo "Jave" in "It would be a huge break from past D practice, and 
 practice in C, C++, Jave, C#, etc."

That's done on purpose to throw off google.
Apr 03 2008
next sibling parent Tower Ty <tytower yahoo.com.au> writes:
Walter Bright Wrote:

 Regan Heath wrote:
 Typo "Jave" in "It would be a huge break from past D practice, and 
 practice in C, C++, Jave, C#, etc."

That's done on purpose to throw off google.

When my cows get through or over my electric fence I am sure I can see them sniggering !
Apr 03 2008
prev sibling parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Walter Bright wrote:
 Regan Heath wrote:
 Typo "Jave" in "It would be a huge break from past D practice, and 
 practice in C, C++, Jave, C#, etc."

That's done on purpose to throw off google.

And that's how we'll win at TIOBE :D -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Apr 04 2008