Another Transitive const solution

Steven Schveighoffer schveiguy at yahoo.com
Wed Apr 9 07:20:44 PDT 2008


"Alex Burton" wrote
>I wonder how many lurkers like me are waiting for D 2.0s const system to be 
>sorted out so that we can start using it.
> Experience shows that const is viral and you are either using it or not 
> using it, and if libraries are using it, then you have to use it or you 
> can't use the libraries.
> So I am not going to write a bunch of D 1.0 code until D 2.0's transitive 
> const is fixed.
>
> Goals of transitive const
> 1. To make the compiler able to perform optimisations based on const.
> 2. To make a documenting const system that is checked by the compiler and 
> useful to the programmer.
>
> Goal 1 is not achievable as has been shown previously in this group :
>
> interface A
> {
> const int getInt();
> };
>
> class B
> {
> const int getInt()
> {
> int x;
> readfln("%d",x); //any c function in a library that might use statics - 
> fread() etc.
> return x;
> }
> };
>
> int main()
> {
> const A a = new B;
>
> int answer = a.getInt()*10 - a.getInt()*100;
> }
>
> The side effects of, and the results of a const member function are not 
> garanteed to be the same.
> No optimisations that change calling order can be done.
> No optimisations that remove redundant calls can be done.
> What other optimisations does transitive const allow ?
>
> I think that transitive const is still useless to the compiler for 
> optimisation purposes, and that has to be left for the pure specifier.

transitive invariant is what allows for optimizations using pure functions. 
In fact, transitive invariant isn't needed, just a well defined invariance 
system is needed.  Transitive invariant helps because it's usually what one 
usually means when one declares a member of a class.  For example, if I 
declare a class like:

class C
{
  int * member;
  pure invariant int f()
  {
      return *member;
  }
}

If D's invariant system isn't transitive, it means that just because I 
declare a C as invariant doesn't make what the members reference invariant. 
Then the pure function isn't allowed to dereference member, because it's not 
sure if member is invariant or not.  We can add keywords to declare that a 
member should be invariant if the class is invariant, but then the author of 
the class has to know that his class will be used in pure functions.  If the 
author doesn't care, then another author writing a pure function cannot use 
C's members, even if C is invariant, and what we are left with is a bunch of 
code that doesn't work with pure functions.  The goal is to make FP 
possible, not hinder it.

What we want is to have what is most common be the default, that any 
variable declared inside a class is part of the class by default, and 
therefore, affected by transitive const/invariant.

We already have exceptions that say 'this isn't part of the class', such as 
static.  What we don't have yet is a way to declare that a variable is not 
part of the class but is stored with the class instance.

>
> Transitive const could still be useful for goal 2 like this :
>
> class A
> {
> int value;
> void set(int x)
> {
> value = x;
> }
> const int get()
> {
> return value;
> }
> };
>
> class B
> {
> part A a1;
> A a2;
> const int get()
> {
> a1.set(7); //compilation error - can't modify a1 in const member function 
> because it is part of B
> a2.set(5); //ok a2 can be modified as it is not part of B it is just an 
> object that we are looking at.
> return a1.get()*a2.get();
> }
> };
>
> So introduce a new keyword : "part" or similar and then we have a powerful 
> const system for goal 2.
> And leave goal 1 for the pure specifier and future developments.

You are saying, let's have variables declared inside a class NOT be 
considered part of the class unless you use the 'part' keyword?  While this 
is a way to solve the problem, I think this would be very error prone.  What 
most people are used to is that when they declare a variable inside a class 
scope, by default it's a member of the class instance.  With your scheme, 
what you will end up with is people will seldom use the 'part' keyword, and 
when pure functions come around, they cannot use any of the non-'part' 
members.  As a result, nobody will use pure functions except for simple math 
functions.  This is not what Walter wants, and if we are going to have pure 
functions, it's not what I want either.  I like how D const is transitive by 
default, although I think there should be a way to make exceptions to that 
rule.

-Steve 





More information about the Digitalmars-d mailing list