| Thread overview | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 09, 2008 Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
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 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.
Alex
| ||||
April 09, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | On 09/04/2008, Alex Burton <alexibu@mac.com> 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. Just curious, but what exactly are you waiting for? Are you waiting for D2 to become stable (i.e. when D3 springs into existence)? > I think that transitive const is still useless to the compiler for optimisation purposes, and that has to be left for the pure specifier. It's a simple chain of logic: pure functions require transitive invariant; transitive invariant requires transitive const. | |||
April 09, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | "Alex Burton" <alexibu@mac.com> wrote in message news:fti5dd$8h7$1@digitalmars.com... >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. What? What does constness in D2 have anything to do with D1? | |||
April 09, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | > 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 :
Correct me if I'm wrong, but I read in an article that there are simple optimizations that can be performed by C++ compilers using const. For example this is preferred:
const int size = container.size();
for(int i = 0; i < size; i++) { ... }
rather than this:
int size = container.size();
for(int i = 0; i < size; i++) { ... }
Because it gives the compiler assurance to know that the size will not change during the loop.
-Craig
| |||
April 09, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | "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 | |||
April 09, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer Wrote: > "Alex Burton" wrote > > 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. I agree, the most common case should be the default. The concept would stay the same though. Whether the keyword is part or notpart or something else I don't know. The basic concept is that reality tells us that not every part of a piece of software is part of every class. Transitive const is at odds with reality, because it assumes that all objects that are members of a class are necessarily part of that class. Alex | |||
April 09, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Craig Black | Craig Black Wrote:
> > 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 :
>
> Correct me if I'm wrong, but I read in an article that there are simple optimizations that can be performed by C++ compilers using const. For example this is preferred:
>
> const int size = container.size();
> for(int i = 0; i < size; i++) { ... }
>
> rather than this:
>
> int size = container.size();
> for(int i = 0; i < size; i++) { ... }
>
> Because it gives the compiler assurance to know that the size will not change during the loop.
>
I am not an expert on such things but :
container is likely to be a container like vector<T> which is a template, which allows the compiler to see what is actually in the size() function.
If all we had was an interface to container, then the compiler couldn't assume that there wasn't a perfectly legal mutable member in there that changed each time size was called, or that the result of size is coming from some other class not part of the container.
Both of these are weaknesses that Walter points out with C++ const system, and he is right, but unfortunately transitive const doesn't fix it.
Alex
| |||
April 09, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | Jarrett Billingsley Wrote:
> "Alex Burton" <alexibu@mac.com> wrote in message news:fti5dd$8h7$1@digitalmars.com...
> >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.
>
> What? What does constness in D2 have anything to do with D1?
>
Knowing that fundamental changes to the language will come in the next version makes me hesitant to start writing lots of code in D1.
| |||
April 09, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Alex Burton | "Alex Burton" <alexibu@mac.com> wrote in message news:ftjfrg$24lu$1@digitalmars.com... > Jarrett Billingsley Wrote: > >> "Alex Burton" <alexibu@mac.com> wrote in message news:fti5dd$8h7$1@digitalmars.com... >> >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. >> >> What? What does constness in D2 have anything to do with D1? >> > Knowing that fundamental changes to the language will come in the next version makes me hesitant to start writing lots of code in D1. > The entire reason for making D1 _D1_ was so that people _would_ start using it. It strikes me as very odd that the exact opposite seems to have happened. You're not the only one to come to this decision. Personally I won't even consider D2 until it's frozen. Furthermore just because you write code in D1 doesn't mean you'll _have_ to start using D2. | |||
April 11, 2008 Re: Another Transitive const solution | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | Jarrett Billingsley wrote:
> "Alex Burton" <alexibu@mac.com> wrote in message news:ftjfrg$24lu$1@digitalmars.com...
>> Jarrett Billingsley Wrote:
>>
>>> "Alex Burton" <alexibu@mac.com> wrote in message
>>> news:fti5dd$8h7$1@digitalmars.com...
>>>> 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.
>>> What? What does constness in D2 have anything to do with D1?
>>>
>> Knowing that fundamental changes to the language will come in the next version makes me hesitant to start writing lots of code in D1.
>>
>
> The entire reason for making D1 _D1_ was so that people _would_ start using it. It strikes me as very odd that the exact opposite seems to have happened. You're not the only one to come to this decision.
>
> Personally I won't even consider D2 until it's frozen. Furthermore just because you write code in D1 doesn't mean you'll _have_ to start using D2.
>
>
I think this idea comes out of the same mindset as Java. You don't want to use something you know is going to be deprecated so soon down the road. Since D2.0 is an evolution of the product rather then a new language it is seen as the next version, why write something that wont work with the next version when you can write it for that version. I think its simply the fact that D2 isn't backwards compatible for a good chunk of things. Porting might end up being a bigger pain then simply waiting is.
I look forward to a lot of the changes in parallel processing and library support coming for D2 and am waiting to start a few projects until D2.0s feature set is frozen, till then I merely putter.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply