digitalmars.D.announce - preparing for const, final, and invariant
- Walter Bright <newshound1 digitalmars.com> May 17 2007
- Frank Benoit <keinfarbton googlemail.com> May 17 2007
- Walter Bright <newshound1 digitalmars.com> May 17 2007
- Manfred Nowak <svv1999 hotmail.com> May 17 2007
- Walter Bright <newshound1 digitalmars.com> May 17 2007
- =?ISO-8859-1?Q?Manuel_K=F6nig?= <ManuelK89 gmx.net> May 18 2007
- Walter Bright <newshound1 digitalmars.com> May 18 2007
- Manfred Nowak <svv1999 hotmail.com> May 18 2007
- Walter Bright <newshound1 digitalmars.com> May 18 2007
- Bill Baxter <dnewsgroup billbaxter.com> May 17 2007
- Walter Bright <newshound1 digitalmars.com> May 17 2007
- Bill Baxter <dnewsgroup billbaxter.com> May 17 2007
- Chris Nicholson-Sauls <ibisbasenji gmail.com> May 17 2007
- Chris Nicholson-Sauls <ibisbasenji gmail.com> May 17 2007
- Manfred Nowak <svv1999 hotmail.com> May 17 2007
- Walter Bright <newshound1 digitalmars.com> May 17 2007
- Manfred Nowak <svv1999 hotmail.com> May 18 2007
- torhu <fake address.dude> May 18 2007
- Manfred Nowak <svv1999 hotmail.com> May 18 2007
- torhu <fake address.dude> May 18 2007
- Manfred Nowak <svv1999 hotmail.com> May 20 2007
- Daniel Keep <daniel.keep.lists gmail.com> May 18 2007
- Walter Bright <newshound1 digitalmars.com> May 18 2007
- Aarti_pl <aarti interia.pl> May 18 2007
- Daniel Keep <daniel.keep.lists gmail.com> May 18 2007
- Aarti_pl <aarti interia.pl> May 18 2007
- Daniel Keep <daniel.keep.lists gmail.com> May 18 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> May 18 2007
- Daniel Keep <daniel.keep.lists gmail.com> May 18 2007
- Don Clugston <dac nospam.com.au> May 18 2007
- Walter Bright <newshound1 digitalmars.com> May 18 2007
- torhu <fake address.dude> May 20 2007
- Walter Bright <newshound1 digitalmars.com> May 20 2007
- janderson <askme me.com> May 20 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> May 26 2007
- Walter Bright <newshound1 digitalmars.com> Jun 04 2007
- Charlie <charlie.fats gmail.com> Jun 04 2007
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Jun 04 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jun 04 2007
- Dave <Dave_member pathlink.com> Jun 04 2007
- Walter Bright <newshound1 digitalmars.com> Jun 04 2007
This is coming for the D 2.0 beta, and it will need some source code
changes. Specifically, for function parameters that are arrays or
pointers, start using 'in' for them.
'in' will mean 'scope const final', which means:
final - the parameter will not be reassigned within the function
const - the function will not attempt to change the contents of what is
referred to
scope - the function will not keep a reference to the parameter's data
that will persist beyond the scope of the function
For example:
int[] g;
void foo(in int[] a)
{
a = [1,2]; // error, a is final
a[1] = 2; // error, a is const
g = a; // error, a is scope
}
Do not use 'in' if you wish to do any of these operations on a
parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be
backwards compatible.
Adding in all those 'in's is tedious, as I'm finding out :-(, but I
think the results will be worth the effort.
May 17 2007
int[] g;
void foo(in int[] a){
g = a.dup; // allowed?
}
May 17 2007
Frank Benoit wrote:int[] g; void foo(in int[] a){ g = a.dup; // allowed? }
Yes.
May 17 2007
Walter Bright wroteFrank Benoit wrote:int[] g; void foo(in int[] a){ g = a.dup; // allowed? }
Yes.
The `.dup'ing an array where a cell contains a reference to the array is allowed too? alias void* T; T[] a; void main(){ T[] g; g.length= 1; g[0]=&g; void f( in T[] p){ a= p.dup; } } That would contradict the given rule. -manfred
May 17 2007
Manfred Nowak wrote:Walter Bright wroteFrank Benoit wrote:int[] g; void foo(in int[] a){ g = a.dup; // allowed? }
The `.dup'ing an array where a cell contains a reference to the array is allowed too? alias void* T; T[] a; void main(){ T[] g; g.length= 1; g[0]=&g; void f( in T[] p){ a= p.dup; } } That would contradict the given rule.
I don't understand. What rule is being violated, and how?
May 17 2007
Walter Bright wrote:Manfred Nowak wrote:Walter Bright wroteFrank Benoit wrote:int[] g; void foo(in int[] a){ g = a.dup; // allowed? }
The `.dup'ing an array where a cell contains a reference to the array is allowed too? alias void* T; T[] a; void main(){ T[] g; g.length= 1; g[0]=&g; void f( in T[] p){ a= p.dup; } } That would contradict the given rule.
I don't understand. What rule is being violated, and how?
I think he is concerning to the scope rule. When 'f' gets called with 'g' as param, then 'a' has implicitly a reference to 'g', namely in a[0]. This would be a violation of the scope rule. -- Regards Manuel
May 18 2007
Manuel König wrote:I think he is concerning to the scope rule. When 'f' gets called with 'g' as param, then 'a' has implicitly a reference to 'g', namely in a[0]. This would be a violation of the scope rule.
Passing things through void* is a way of escaping the type checking, and if you break the rules by doing so, your program might break.
May 18 2007
Walter Bright wrotePassing things through void* is a way of escaping the type checking, and if you break the rules by doing so, your program might break.
The compiler seems to follow the specs which say | A pointer T* can be implicitly converted to one of the following: | | void* There is no hint in the specs that this even _implicite_ possible conversion is breaking the security of the type system. But let me assume for now, that this implicite conversion is an exception and that "breaks type system" will be included in the specs. Now how about using a circular list, i.e avoiding use of `void *' struct T{ T* next; } T a; void main(){ T g; g.next= &g; void f( in T p){ a= *(p.next); // *_ } f( g); // breaking of scope rule? } -manfred
May 18 2007
Manfred Nowak wrote:Walter Bright wrotePassing things through void* is a way of escaping the type checking, and if you break the rules by doing so, your program might break.
The compiler seems to follow the specs which say | A pointer T* can be implicitly converted to one of the following: | | void* There is no hint in the specs that this even _implicite_ possible conversion is breaking the security of the type system. But let me assume for now, that this implicite conversion is an exception and that "breaks type system" will be included in the specs. Now how about using a circular list, i.e avoiding use of `void *' struct T{ T* next; } T a; void main(){ T g; g.next= &g; void f( in T p){ a= *(p.next); // *_ } f( g); // breaking of scope rule? }
Yes, you're breaking it.
May 18 2007
Walter Bright wrote:This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them. 'in' will mean 'scope const final', which means: final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function For example: int[] g; void foo(in int[] a) { a = [1,2]; // error, a is final a[1] = 2; // error, a is const g = a; // error, a is scope } Do not use 'in' if you wish to do any of these operations on a parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be backwards compatible. Adding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.
So if you don't use 'in' then the behavior will the the same as not using anything (or using 'in') in D1.0? --bb
May 17 2007
Bill Baxter wrote:So if you don't use 'in' then the behavior will the the same as not using anything (or using 'in') in D1.0?
Right - except that you won't be able to past string literals to them (as string literals will be const).
May 17 2007
Walter Bright wrote:Bill Baxter wrote:So if you don't use 'in' then the behavior will the the same as not using anything (or using 'in') in D1.0?
Right - except that you won't be able to past string literals to them (as string literals will be const).
Ok. Well that is actually a little nicer than C++ where every reference param you don't intend to modify needs to be marked 'const'. Nicer in the sense that 'in' is shorter to type, at least, and in that it won't make Don Clugston cringe every time he has to type it. What about method signatures that want 'this' to be an 'in' param. Trailing 'in' like C++? void aMethod() in { writefln(x, toString); } Seems a little strange but I'm sure I'd get used to it. I guess const would mean the same thing, though, since 'this' is already final and scope doesn't really apply. --bb
May 17 2007
Bill Baxter wrote:Walter Bright wrote:Bill Baxter wrote:So if you don't use 'in' then the behavior will the the same as not using anything (or using 'in') in D1.0?
Right - except that you won't be able to past string literals to them (as string literals will be const).
Ok. Well that is actually a little nicer than C++ where every reference param you don't intend to modify needs to be marked 'const'. Nicer in the sense that 'in' is shorter to type, at least, and in that it won't make Don Clugston cringe every time he has to type it. What about method signatures that want 'this' to be an 'in' param. Trailing 'in' like C++? void aMethod() in { writefln(x, toString); }
Assuming they haven't changed, this would break pre-conditions.Seems a little strange but I'm sure I'd get used to it. I guess const would mean the same thing, though, since 'this' is already final and scope doesn't really apply. --bb
Since this may have its uses, and so long as the meaning is very clear, I could live with 'const' in that position. -- Chris Nicholson-Sauls
May 17 2007
Walter Bright wrote:This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them. 'in' will mean 'scope const final', which means: final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function For example: int[] g; void foo(in int[] a) { a = [1,2]; // error, a is final a[1] = 2; // error, a is const g = a; // error, a is scope } Do not use 'in' if you wish to do any of these operations on a parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be backwards compatible. Adding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.
Sounds good to me. How soon can we expect 2.0beta? -- Chris Nicholson-Sauls
May 17 2007
Walter Bright wrotescope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function
g = a; // error, a is scope
In this example the function assigns to a variable living outside of the scope of the function. Therefore the function does not keep that reference itself---and that rule should not fire. In addition: if the rule's wording is changed to match that example, then it becomes unclear, whether `writefln( &a)' is allowed because `writefln' might store that reference somewhere---especially via OS in a file, which might be read in later by the calling process. In case of disallowance that rule would disallow printing too. -manfred
May 17 2007
Manfred Nowak wrote:Walter Bright wrotescope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function
g = a; // error, a is scope
In this example the function assigns to a variable living outside of the scope of the function. Therefore the function does not keep that reference itself---and that rule should not fire.
Since it's storing a reference that will "persist beyond the scope of the function", it's illegal.In addition: if the rule's wording is changed to match that example, then it becomes unclear, whether `writefln( &a)' is allowed because `writefln' might store that reference somewhere---especially via OS in a file, which might be read in later by the calling process. In case of disallowance that rule would disallow printing too.
Making copies is allowed.
May 17 2007
Walter Bright wroteMaking copies is allowed.
A copy of a reference is not the reference itself? Then `g = a;' does not make a copy of the adress contained in `a'? WHat does it do then? -manfred
May 18 2007
Manfred Nowak wrote:Walter Bright wroteMaking copies is allowed.
A copy of a reference is not the reference itself? Then `g = a;' does not make a copy of the adress contained in `a'?
It does make a copy, but if g is 'scope', you're only allowed to have local copies of a. This would be fine: int[] b = a;WHat does it do then? -manfred
May 18 2007
torhu wroteIt does make a copy, but if g is 'scope', you're only allowed to have local copies of a. This would be fine: int[] b = a;
I understand this exactly as you say it: only local copies are allowed! But `writef( &b);' as well as `writef( &a);' may create global copies, i.e. at least not local copies. If this holds, then the scope-rule forbids printing out. But Walter responds with "Making copies is allowed." Which seems to mean, that global copies are allowed by printing out---or his remark has nothing to do with the problem stated. How to resolve this contradiction? -manfred
May 18 2007
Manfred Nowak wrote:torhu wroteIt does make a copy, but if g is 'scope', you're only allowed to have local copies of a. This would be fine: int[] b = a;
I understand this exactly as you say it: only local copies are allowed! But `writef( &b);' as well as `writef( &a);' may create global copies, i.e. at least not local copies. If this holds, then the scope-rule forbids printing out. But Walter responds with "Making copies is allowed." Which seems to mean, that global copies are allowed by printing out---or his remark has nothing to do with the problem stated. How to resolve this contradiction?
It's not a contradiction. Only references that are actually inside your application are relevant for this rule.
May 18 2007
torhu wroteIt's not a contradiction. Only references that are actually inside your application are relevant for this rule.
Very true. If one restricts the application to local copies, then the rule cannot be violated---but then the rule is ineffective also. This seems to shout for a formalization of the scope rule. -manfred
May 20 2007
Note: I've read the reply where you clarified that this is to allow static things like string literals to be passed in. Walter Bright wrote:This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them. 'in' will mean 'scope const final', which means: final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function For example: int[] g; void foo(in int[] a) { a = [1,2]; // error, a is final a[1] = 2; // error, a is const g = a; // error, a is scope } Do not use 'in' if you wish to do any of these operations on a parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be backwards compatible.
Is final really necessary? I can understand const and scope; but is it really a problem if the function rebinds the argument? I mean, that shouldn't affect the calling code in the slightest, should it? void foo(const scope int[] a) { a = [1,2]; } static bar = [3,4]; foo(bar); assert( bar == [3,4] ); // This should still hold, right? There are a few functions I've written which re-bind the argument as they run; the simplest examples being functions that process strings (effectively, it just loops until there's just an empty slice left). Apart from that, I don't think there's any problems with doing this. Oh well; I'll just have to declare an extra argument. :PAdding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.
Actually, I was thinking of doing this anyway so that my argument lists are nice and symmetric (qualifiers on all of them, instead of just ref and out). Now I have an excellent reason to do so other than my pedantic-ness. :) One question: is there a keyword for "normal" arguments--for instance, I know that most variables are "auto" if you don't specify the storage class explicitly. I can't imagine where it would be useful; just curious. At any rate, looks spiffy. -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 18 2007
Daniel Keep wrote:Is final really necessary?
No. It's there because nearly all the time, one won't be rebinding a parameter, so making it easier to be final seems like a good idea.I can understand const and scope; but is it really a problem if the function rebinds the argument? I mean, that shouldn't affect the calling code in the slightest, should it?
No, it does not affect the caller. Only the callee.void foo(const scope int[] a) { a = [1,2]; } static bar = [3,4]; foo(bar); assert( bar == [3,4] ); // This should still hold, right?
Yes.There are a few functions I've written which re-bind the argument as they run; the simplest examples being functions that process strings (effectively, it just loops until there's just an empty slice left). Apart from that, I don't think there's any problems with doing this. Oh well; I'll just have to declare an extra argument. :PAdding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.
Actually, I was thinking of doing this anyway so that my argument lists are nice and symmetric (qualifiers on all of them, instead of just ref and out). Now I have an excellent reason to do so other than my pedantic-ness. :) One question: is there a keyword for "normal" arguments--
No. We could use 'auto' for that, but what's the point <g>.for instance, I know that most variables are "auto" if you don't specify the storage class explicitly. I can't imagine where it would be useful; just curious. At any rate, looks spiffy. -- Daniel
May 18 2007
Walter Bright pisze:This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them. 'in' will mean 'scope const final', which means: final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function For example: int[] g; void foo(in int[] a) { a = [1,2]; // error, a is final a[1] = 2; // error, a is const g = a; // error, a is scope } Do not use 'in' if you wish to do any of these operations on a parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be backwards compatible. Adding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.
I want to ask about something opposite to above example... Will it be possible to pass ownership of object? I mean that when you pass object by reference to function/class/member variable you can still modify this object from outside of function/class. It breaks encapsulation in program. Example: import std.stdio; public class TestX { char[] value; char[] toString() { return value; } } public class TestMain { TestX x; } void main(char[][] args) { TestX parameter = new TestX(); parameter.value = "First assignment"; TestMain tmain = new TestMain(); tmain.x = parameter; parameter.value = "Second assignment"; writefln(tmain.x); } Notice that tmain.x value has changed although I would like just to set once, and have second assignment to parameter illegal... When using setters and getters problem is even more visible.... How to achieve proper behavior with new final/const/invariant/scope?? Regards Marcin Kuszczak (aarti_pl)
May 18 2007
Aarti_pl wrote:I want to ask about something opposite to above example... Will it be possible to pass ownership of object? I mean that when you pass object by reference to function/class/member variable you can still modify this object from outside of function/class. It breaks encapsulation in program. Example: import std.stdio; public class TestX { char[] value; char[] toString() { return value; } } public class TestMain { TestX x; } void main(char[][] args) { TestX parameter = new TestX(); parameter.value = "First assignment"; TestMain tmain = new TestMain(); tmain.x = parameter; parameter.value = "Second assignment"; writefln(tmain.x); } Notice that tmain.x value has changed although I would like just to set once, and have second assignment to parameter illegal... When using setters and getters problem is even more visible.... How to achieve proper behavior with new final/const/invariant/scope?? Regards Marcin Kuszczak (aarti_pl)
I don't think the new const, final & invariant are going to help you any. Basically, you seem to be complaining that reference semantics are... well, reference semantics. That's like complaining that water is wet :P There's a few things I can think of to get the behaviour you want. 1. Use a write-once setter for 'value'. You can either create a nullable template, or use a flag to ensure external code can only set it once. 1.a. A "nicer" approach would be to set it in the constructor, and then either mark it "final" (with the new final), or only write a public getter function. 2. Use a struct instead; no references, no indirect changes. 3. Take a private copy of the object by writing a .dup method. -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 18 2007
Daniel Keep pisze:Aarti_pl wrote:I want to ask about something opposite to above example... Will it be possible to pass ownership of object? I mean that when you pass object by reference to function/class/member variable you can still modify this object from outside of function/class. It breaks encapsulation in program. Example: import std.stdio; public class TestX { char[] value; char[] toString() { return value; } } public class TestMain { TestX x; } void main(char[][] args) { TestX parameter = new TestX(); parameter.value = "First assignment"; TestMain tmain = new TestMain(); tmain.x = parameter; parameter.value = "Second assignment"; writefln(tmain.x); } Notice that tmain.x value has changed although I would like just to set once, and have second assignment to parameter illegal... When using setters and getters problem is even more visible.... How to achieve proper behavior with new final/const/invariant/scope?? Regards Marcin Kuszczak (aarti_pl)
I don't think the new const, final & invariant are going to help you any. Basically, you seem to be complaining that reference semantics are... well, reference semantics. That's like complaining that water is wet :P
The problem here is that current behavior breaks encapsulation - you can change already passed value from outside of object, when contract is that you can set it only with setter. Imagine consequences in multithreaded application, when in the middle of function your data suddenly change... But also with single threaded application it can be real problem when you change referenced object by mistake. So it is more like complaining that water is dry when it should be wet in fact :-) I know that other languages also have same problem, but I think that D can do better.There's a few things I can think of to get the behaviour you want. 1. Use a write-once setter for 'value'. You can either create a nullable template, or use a flag to ensure external code can only set it once.
Could you please give example? I don't know how to achieve this behavior with this method...1.a. A "nicer" approach would be to set it in the constructor, and then either mark it "final" (with the new final), or only write a public getter function.
I think that rather invariant? Final will not disallow changing of referenced object. And I am afraid that it won't help anyway, it would be still possible to change value from outside... Using only getter and passing reference in constructor also doesn't help. You can still also modify variable from outside...2. Use a struct instead; no references, no indirect changes.
Ok. I didn't think about it. But it is basically same as below, so please see comment below. Probably you have also problem when struct has references inside...3. Take a private copy of the object by writing a .dup method.
Yes that is possible solution, but program would be much faster (no unnecessary copies) with other solution...-- Daniel
BR Marcin Kuszczak (aarti_pl)
May 18 2007
Aarti_pl wrote:Daniel Keep pisze:Aarti_pl wrote:I want to ask about something opposite to above example... Will it be possible to pass ownership of object? I mean that when you pass object by reference to function/class/member variable you can still modify this object from outside of function/class. It breaks encapsulation in program. Example: import std.stdio; public class TestX { char[] value; char[] toString() { return value; } } public class TestMain { TestX x; } void main(char[][] args) { TestX parameter = new TestX(); parameter.value = "First assignment"; TestMain tmain = new TestMain(); tmain.x = parameter; parameter.value = "Second assignment"; writefln(tmain.x); } Notice that tmain.x value has changed although I would like just to set once, and have second assignment to parameter illegal... When using setters and getters problem is even more visible.... How to achieve proper behavior with new final/const/invariant/scope?? Regards Marcin Kuszczak (aarti_pl)
I don't think the new const, final & invariant are going to help you any. Basically, you seem to be complaining that reference semantics are... well, reference semantics. That's like complaining that water is wet :P
The problem here is that current behavior breaks encapsulation - you can change already passed value from outside of object, when contract is that you can set it only with setter. Imagine consequences in multithreaded application, when in the middle of function your data suddenly change... But also with single threaded application it can be real problem when you change referenced object by mistake. So it is more like complaining that water is dry when it should be wet in fact :-) I know that other languages also have same problem, but I think that D can do better.
Ok: so the problem is that because D's class system doesn't have a concept of ownership, encapsulation can be violated. That said, I've never seen an OO language that *did* have a concept of ownership, so I don't know what we could do to "fix" it :PThere's a few things I can think of to get the behaviour you want. 1. Use a write-once setter for 'value'. You can either create a nullable template, or use a flag to ensure external code can only set it once.
Could you please give example? I don't know how to achieve this behavior with this method...
class TestX { private { char[] _value; bool _value_set = false; } char[] value(char[] v) { if( _value_set ) assert(false, "cannot set value more than once!"); _value = v; _value_set = true; return v; } char[] value() { return _value; } }1.a. A "nicer" approach would be to set it in the constructor, and then either mark it "final" (with the new final), or only write a public getter function.
I think that rather invariant? Final will not disallow changing of referenced object. And I am afraid that it won't help anyway, it would be still possible to change value from outside... Using only getter and passing reference in constructor also doesn't help. You can still also modify variable from outside...
Since D2.0 hasn't been released yet, I don't know for certain, but I would hope it would be possible to create a final invariant member. In this case, you can assign to it *only* during the constructor, and you can only assign something to it which will never change. But then, I'm not sure if that would really work or not.2. Use a struct instead; no references, no indirect changes.
Ok. I didn't think about it. But it is basically same as below, so please see comment below. Probably you have also problem when struct has references inside...
Mmm.3. Take a private copy of the object by writing a .dup method.
Yes that is possible solution, but program would be much faster (no unnecessary copies) with other solution...-- Daniel
BR Marcin Kuszczak (aarti_pl)
Here's another idea I had. This *might* work come D2.0 (but again, I don't know for certain). The idea here is that if we are passed a possibly mutable value, we take a private copy of it since this is the only way we can ensure no one else can mutate it. BUT, if we are passed an invariant string, we just take a reference since the compiler is effectively guaranteeing that its contents will never, ever change. Incidentally, I'm also assuming the whole "casting to const" thing works. class TestX { private { char[] _value; } // Copy v: no external mutations! char[] value(char[] v) { _value = v.dup; return v; } // Invariant, so a reference to it is fine char[] value(invariant char[] v) { _value = v; return v; } // Return const: no one calling this can modify it, even though they // have a reference! const char[] value() { return cast(const char[])_value; } } So maybe you will be able to get what you want. Will be interesting to find out :) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 18 2007
Daniel Keep wrote:// Invariant, so a reference to it is fine char[] value(invariant char[] v) { _value = v; return v; }
But a mutable reference to it shouldn't be fine. So IMHO this should fail because you're trying to return an invariant char[] as a mutable char[]...// Return const: no one calling this can modify it, even though they // have a reference! const char[] value() { return cast(const char[])_value; }
I think that explicit cast should be unneeded. Mutable to const should be possible through an implicit cast..
May 18 2007
Frits van Bommel wrote:Daniel Keep wrote:// Invariant, so a reference to it is fine char[] value(invariant char[] v) { _value = v; return v; }
But a mutable reference to it shouldn't be fine. So IMHO this should fail because you're trying to return an invariant char[] as a mutable char[]...
*grumbles* Fine, Mr. Pick On My Mistakes...invariant char[] value(invariant char[] v) { _value = v; return v; }
There, all better now? :) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 18 2007
Walter Bright wrote:This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them. 'in' will mean 'scope const final', which means: final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function
Looks great, although somewhat overwhelming for a newcomer. Will functions be overloadable on all of these? Anyway, it sounds as though we'll see 2.0 beta 1 before DMD 1.15 ?
May 18 2007
Don Clugston wrote:Walter Bright wrote:final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function
Looks great, although somewhat overwhelming for a newcomer. Will functions be overloadable on all of these?
Just for const.Anyway, it sounds as though we'll see 2.0 beta 1 before DMD 1.15 ?
Probably <g>.
May 18 2007
Walter Bright wrote:This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them. 'in' will mean 'scope const final', which means: final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function For example: int[] g; void foo(in int[] a) { a = [1,2]; // error, a is final a[1] = 2; // error, a is const g = a; // error, a is scope } Do not use 'in' if you wish to do any of these operations on a parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be backwards compatible. Adding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.
If you've got a C library with a header file containing this: // C header file void f(const char* p); Is there any reason why you should think twice before turning it into this D code, and link it with the C library, not knowing anything about the implementation of f? // D import module extern (C) void f(in char* p); Without reading the docs for f, would it be better to just go with 'const'? In that case it won't be backwards compatible with D 1.0 anymore. If I get the meaning of 'scope' correctly, that's the one that can cause problems here.
May 20 2007
torhu wrote:If you've got a C library with a header file containing this: // C header file void f(const char* p); Is there any reason why you should think twice before turning it into this D code, and link it with the C library, not knowing anything about the implementation of f? // D import module extern (C) void f(in char* p); Without reading the docs for f, would it be better to just go with 'const'? In that case it won't be backwards compatible with D 1.0 anymore. If I get the meaning of 'scope' correctly, that's the one that can cause problems here.
I'd go with: f(const char* p); because that expresses the C semantics. Using 'in' will cause problems if f() stores p somewhere.
May 20 2007
Perhaps we need a D2.0.learn newsgroup? Would we also need to make 2.0 of the others? -Joel
May 20 2007
I've only now been able to read this thread, so, just some simple questions: Walter Bright wrote:This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them. 'in' will mean 'scope const final', which means: final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function
Does this mean you have finished a working design for const/final/invariant/etc. ? If so, then what is the type of fooptr here? : final foo; auto fooptr = &foo;For example: int[] g; void foo(in int[] a) { a = [1,2]; // error, a is final a[1] = 2; // error, a is const g = a; // error, a is scope } Do not use 'in' if you wish to do any of these operations on a parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be backwards compatible. Adding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.
Whoa there, that idea of 'scope' being the default togheter with 'const' and 'final', where did that came from? I understand why (and agree) that 'final' and 'const' should be the default type modifiers for function parameters, but why 'scope' as well? -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 26 2007
Bruno Medeiros wrote:Whoa there, that idea of 'scope' being the default togheter with 'const' and 'final', where did that came from? I understand why (and agree) that 'final' and 'const' should be the default type modifiers for function parameters, but why 'scope' as well?
Because most function parameters are scope already.
Jun 04 2007
I'm appalled, both that this is pretty much assured to be in D , and that the community seems to be behind it. I thought that the reason Walter didn't want const was because of its added complexity , so instead he introduces _3_ new keywords ? Does no one else feel like this is using a machine gun to kill a fly ? I understand the need for immutable data when writing libraries, but 'scope const final MyClass myInstance' ?!? Theres got to be a better way. I know this sounds over-dramatic, but if this is the direction D is headed, then count me out. I loved D because if its elegant and powerful simplicity, I think D has strayed way to far from its original goal. If anyone feels like _this_ implementation for const ( not the usefulness of const mind you ) is not for D, then please speak up or we all might end up losing our favorite language. Charlie Walter Bright wrote:This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them. 'in' will mean 'scope const final', which means: final - the parameter will not be reassigned within the function const - the function will not attempt to change the contents of what is referred to scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function For example: int[] g; void foo(in int[] a) { a = [1,2]; // error, a is final a[1] = 2; // error, a is const g = a; // error, a is scope } Do not use 'in' if you wish to do any of these operations on a parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be backwards compatible. Adding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.
Jun 04 2007
"Charlie" <charlie.fats gmail.com> wrote in message news:46649DD9.1010801 gmail.com...I'm appalled, both that this is pretty much assured to be in D , and that the community seems to be behind it. I thought that the reason Walter didn't want const was because of its added complexity , so instead he introduces _3_ new keywords ? Does no one else feel like this is using a machine gun to kill a fly ? I understand the need for immutable data when writing libraries, but 'scope const final MyClass myInstance' ?!? Theres got to be a better way. I know this sounds over-dramatic, but if this is the direction D is headed, then count me out. I loved D because if its elegant and powerful simplicity, I think D has strayed way to far from its original goal. If anyone feels like _this_ implementation for const ( not the usefulness of const mind you ) is not for D, then please speak up or we all might end up losing our favorite language.
I was beginning to think I was the only one. It doesn't seem any easier than the C++ style const-ness at all. If anything it's more complex. Instead of "here a const, there a const, everywhere a const * const" it seems like it'll be "here a const, there a final, everywhere an invariant scope int[new]" :P
Jun 04 2007
Jarrett Billingsley wrote:"Charlie" <charlie.fats gmail.com> wrote in message news:46649DD9.1010801 gmail.com...I'm appalled, both that this is pretty much assured to be in D , and that the community seems to be behind it. I thought that the reason Walter didn't want const was because of its added complexity , so instead he introduces _3_ new keywords ? Does no one else feel like this is using a machine gun to kill a fly ? I understand the need for immutable data when writing libraries, but 'scope const final MyClass myInstance' ?!? Theres got to be a better way. I know this sounds over-dramatic, but if this is the direction D is headed, then count me out. I loved D because if its elegant and powerful simplicity, I think D has strayed way to far from its original goal. If anyone feels like _this_ implementation for const ( not the usefulness of const mind you ) is not for D, then please speak up or we all might end up losing our favorite language.
I was beginning to think I was the only one. It doesn't seem any easier than the C++ style const-ness at all. If anything it's more complex. Instead of "here a const, there a const, everywhere a const * const" it seems like it'll be "here a const, there a final, everywhere an invariant scope int[new]" :P
I think we should wait and see how it comes out. Of course expressing your doubts and misgivings is a good thing too, but, yeh, let's try not to be over-dramatic. Naturally the discussion here tends to revolve around the cases that aren't obvious or straightforward, because the obvious, easy cases need no discussion. So it's natural that it ends up sounding like "everywhere an invariant scope int[new]", but I suspect in typical code such things will be uncommon. I'm not sure about this int[*] thing though. That will probably require a lot of changes whether int[*] ends up meaning resizeable or not. But come on, you have to admit that slices are a little dicey, and giving the compiler a way to detect bogus usage of a slice will be good. They're supposed to be a safer alternative to naked pointers, but instead they introduce their own equivalently dangerous set of gotchas due to the ambiguity of ownership. Other than that, I think pretty much all of the changes Walter has mentioned will be ignorable. --bb
Jun 04 2007
Bill Baxter wrote:Jarrett Billingsley wrote:"Charlie" <charlie.fats gmail.com> wrote in message news:46649DD9.1010801 gmail.com...I'm appalled, both that this is pretty much assured to be in D , and that the community seems to be behind it. I thought that the reason Walter didn't want const was because of its added complexity , so instead he introduces _3_ new keywords ? Does no one else feel like this is using a machine gun to kill a fly ? I understand the need for immutable data when writing libraries, but 'scope const final MyClass myInstance' ?!? Theres got to be a better way. I know this sounds over-dramatic, but if this is the direction D is headed, then count me out. I loved D because if its elegant and powerful simplicity, I think D has strayed way to far from its original goal. If anyone feels like _this_ implementation for const ( not the usefulness of const mind you ) is not for D, then please speak up or we all might end up losing our favorite language.
I was beginning to think I was the only one. It doesn't seem any easier than the C++ style const-ness at all. If anything it's more complex. Instead of "here a const, there a const, everywhere a const * const" it seems like it'll be "here a const, there a final, everywhere an invariant scope int[new]" :P
I think we should wait and see how it comes out. Of course expressing your doubts and misgivings is a good thing too, but, yeh, let's try not to be over-dramatic. Naturally the discussion here tends to revolve around the cases that aren't obvious or straightforward, because the obvious, easy cases need no discussion. So it's natural that it ends up sounding like "everywhere an invariant scope int[new]", but I suspect in typical code such things will be uncommon.
Recalling the resistance that Walter originally had to adding const (the 'loose' semantics of C++ const and the concern about "littering" D code w/ const), I too think it will be wise to see what Walter has come up with. I'm pretty confident it will be both better and less onerous than C++ const for a majority of situations given the quality of design (of D) in other areas.I'm not sure about this int[*] thing though. That will probably require a lot of changes whether int[*] ends up meaning resizeable or not. But come on, you have to admit that slices are a little dicey, and giving the compiler a way to detect bogus usage of a slice will be good. They're supposed to be a safer alternative to naked pointers, but instead they introduce their own equivalently dangerous set of gotchas due to the ambiguity of ownership. Other than that, I think pretty much all of the changes Walter has mentioned will be ignorable. --bb
Jun 04 2007
Charlie wrote:I'm appalled, both that this is pretty much assured to be in D , and that the community seems to be behind it. I thought that the reason Walter didn't want const was because of its added complexity , so instead he introduces _3_ new keywords ? Does no one else feel like this is using a machine gun to kill a fly ? I understand the need for immutable data when writing libraries, but 'scope const final MyClass myInstance' ?!? Theres got to be a better way. I know this sounds over-dramatic, but if this is the direction D is headed, then count me out. I loved D because if its elegant and powerful simplicity, I think D has strayed way to far from its original goal. If anyone feels like _this_ implementation for const ( not the usefulness of const mind you ) is not for D, then please speak up or we all might end up losing our favorite language.
Actually, I quite empathize with your viewpoint. I worry that the final, const, invariant thing is too complicated. But there are some mitigating factors: 1) Just as in C++, you can pretty much ignore final, const, and invariant if they don't appeal to you. I don't bother using const in my C++ code. 2) The transitive nature of const means that there are a lot fewer const's you have to write. 3) Using D's type inference capability, a lot fewer types (and their attendant const's) need to be written. 4) It provides information that is actually useful to the compiler. 5) Scope has the promise of enabling reference counting to be far more efficient than is possible in C++. 6) Working together, these features move us towards supporting the functional programming paradigm better. FP is very important for the future, as it is very adaptable to parallel programming. 7) They make interfaces much more self-documenting. 8) They can make automated code analysis tools more effective. Automated code analysis is big business and is getting to be far more important as security consultants are brought in to analyze code for correctness, security, etc. Wall Street in particular is very interested in this stuff. 9) So far, in my work to make Phobos const-correct, it hasn't been the annoyance I thought it would be.
Jun 04 2007









Walter Bright <newshound1 digitalmars.com> 