digitalmars.D - Immutable arrays for Walter and rest of us.
- "Andrew Fedoniouk" <news terrainformatica.com> Jun 29 2005
- Victor Nakoryakov <nail-mail mail.ru> Jun 30 2005
- "Regan Heath" <regan netwin.co.nz> Jun 30 2005
- Kramer <Kramer_member pathlink.com> Jun 30 2005
- Brad Beveridge <brad somewhere.net> Jun 30 2005
- "Andrew Fedoniouk" <news terrainformatica.com> Jun 30 2005
- Brad Beveridge <brad somewhere.net> Jun 30 2005
- Brad Beveridge <brad somewhere.net> Jun 30 2005
- "Andrew Fedoniouk" <news terrainformatica.com> Jun 30 2005
- AJG <AJG_member pathlink.com> Jun 30 2005
- Vathix <chris dprogramming.com> Jun 30 2005
- Brad Beveridge <brad somewhere.net> Jun 30 2005
- Vathix <chris dprogramming.com> Jun 30 2005
- "Walter" <newshound digitalmars.com> Jun 30 2005
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> Jun 30 2005
- AJG <AJG_member pathlink.com> Jun 30 2005
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> Jun 30 2005
- AJG <AJG_member pathlink.com> Jun 30 2005
- "Regan Heath" <regan netwin.co.nz> Jun 30 2005
- Trevor Parscal <trevorparscal hotmail.com> Jul 05 2005
- AJG <AJG_member pathlink.com> Jul 05 2005
- "Regan Heath" <regan netwin.co.nz> Jul 05 2005
- "Regan Heath" <regan netwin.co.nz> Jun 30 2005
- "Andrew Fedoniouk" <news terrainformatica.com> Jun 30 2005
- "Regan Heath" <regan netwin.co.nz> Jun 30 2005
- "Andrew Fedoniouk" <news terrainformatica.com> Jun 30 2005
- "Regan Heath" <regan netwin.co.nz> Jun 30 2005
- "Andrew Fedoniouk" <news terrainformatica.com> Jul 01 2005
- "Regan Heath" <regan netwin.co.nz> Jul 01 2005
- "Regan Heath" <regan netwin.co.nz> Jul 01 2005
- "Andrew Fedoniouk" <news terrainformatica.com> Jun 30 2005
- "Walter" <newshound digitalmars.com> Jul 01 2005
- "Regan Heath" <regan netwin.co.nz> Jul 01 2005
- AJG <AJG_member pathlink.com> Jul 01 2005
- "Regan Heath" <regan netwin.co.nz> Jul 01 2005
- AJG <AJG_member pathlink.com> Jul 01 2005
- Kevin Bealer <Kevin_member pathlink.com> Jul 01 2005
- "Walter" <newshound digitalmars.com> Jul 01 2005
- Sean Kelly <sean f4.ca> Jul 01 2005
- Carlos Santander <csantander619 gmail.com> Jul 01 2005
- "Walter" <newshound digitalmars.com> Jul 02 2005
- "Dave" <Dave_member pathlink.com> Jul 02 2005
- "Dave" <Dave_member pathlink.com> Jul 04 2005
I would like to discuss one of my previous ideas again
as it seems it was lost in the fire.
I think below is the best compromise we can get. In fact
as more I am looking on it as more I am sure that it
not even compromise - it is "well done immutables".
Idea is to extend typesystem with a new type: immutable (const, readonly)
array and pointer.
Proposed notation of immutable array type is as:
typename#[]
Proposed notation of immutable pointer is as:
typename#*
Immutable array as a type has exactly the same set
of properties and methods as array except of mutators:
opIndexAssign and
int length(int newlength)
Casting rules between array#[] and array[] are obvious:
char#[] is1;
char[] s1;
is1 = s1; // ok.
s1 = is1; // compile time (CT) err.
Examples:
s1[0] = 'a'; // ok
is1[0] = 'a'; // CT err.
s1.length = 1; // ok
is1.length = 1; // CT err.
--------------------------------
String and array literals are immutable by definition:
char#[] slit1 = "Hello world"; // ok
char[] s1 = "Hello world"; // CT err.
Sidenote:
In C++, by historical reasons, string literals
have type char* and not const char* which is
imho bad and needs to be changed.
------------------------------
This approach will give us readonlyness without major changes
in language notation and architecture.
This approach is free from C++ "const syntactical madness" where
const is used for three different things and looks ugly sometimes.
Clear differentiation of built-in reference types (array and struct) onto
mutable and immutable versions will increase "fullness" of D's
balanced type system.
The thing is that char[] is from one side is atomic type
and it is pretty natural to human to interpret it as just lets say
atomic int. But at the same time it is a reference to some
possibly shared data. This is why arrays and pointers shall
exist in two forms.
As a rule char[] is buffer/owner and char#[] is an immutable slice -
consumer has no rights to change it as it will damage
integrity state of the owner.
-------------------------------------------
Possible variations of immutable type notation I've considered:
1) typename#[]
2) typename$[]
3) typename []
4) typename[] const - not good as it conflicts with
C++ cases visually.
typename#[] probably is not the best variant
of notation though. Ideas anyone?
--------------------------------------------
I think it makes sense to add opSliceConst to the list of
overloadable operators.
--------------------------------------------
Having readonlyness interpreted and implemented
this way will finally reconcile const and no-const camps. I hope.
Andrew.
Jun 29 2005
Yep, good idea. But you're not the first, and I think not the last who suggest some solution for constness. To me suggestion seems to be ignored. -- Victor (aka nail) Nakoryakov nail-mail<at>mail<dot>ru Krasnoznamensk, Moscow, Russia
Jun 30 2005
Not a bad idea. I prefer the solution I've mentioned a few times already. I just hope Walter gives us some indication of what he's thinking at some stage. (hint, hint) Regan On Wed, 29 Jun 2005 23:06:12 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:I would like to discuss one of my previous ideas again as it seems it was lost in the fire. I think below is the best compromise we can get. In fact as more I am looking on it as more I am sure that it not even compromise - it is "well done immutables". Idea is to extend typesystem with a new type: immutable (const, readonly) array and pointer. Proposed notation of immutable array type is as: typename#[] Proposed notation of immutable pointer is as: typename#* Immutable array as a type has exactly the same set of properties and methods as array except of mutators: opIndexAssign and int length(int newlength) Casting rules between array#[] and array[] are obvious: char#[] is1; char[] s1; is1 = s1; // ok. s1 = is1; // compile time (CT) err. Examples: s1[0] = 'a'; // ok is1[0] = 'a'; // CT err. s1.length = 1; // ok is1.length = 1; // CT err. -------------------------------- String and array literals are immutable by definition: char#[] slit1 = "Hello world"; // ok char[] s1 = "Hello world"; // CT err. Sidenote: In C++, by historical reasons, string literals have type char* and not const char* which is imho bad and needs to be changed. ------------------------------ This approach will give us readonlyness without major changes in language notation and architecture. This approach is free from C++ "const syntactical madness" where const is used for three different things and looks ugly sometimes. Clear differentiation of built-in reference types (array and struct) onto mutable and immutable versions will increase "fullness" of D's balanced type system. The thing is that char[] is from one side is atomic type and it is pretty natural to human to interpret it as just lets say atomic int. But at the same time it is a reference to some possibly shared data. This is why arrays and pointers shall exist in two forms. As a rule char[] is buffer/owner and char#[] is an immutable slice - consumer has no rights to change it as it will damage integrity state of the owner. ------------------------------------------- Possible variations of immutable type notation I've considered: 1) typename#[] 2) typename$[] 3) typename [] 4) typename[] const - not good as it conflicts with C++ cases visually. typename#[] probably is not the best variant of notation though. Ideas anyone? -------------------------------------------- I think it makes sense to add opSliceConst to the list of overloadable operators. -------------------------------------------- Having readonlyness interpreted and implemented this way will finally reconcile const and no-const camps. I hope. Andrew.
Jun 30 2005
And since it has been suggested so many times and IMO a very worth while idea/feature, if Walter does not want to add it, then we need some practices/idioms for D on how to simulate it. -Kramer In article <opss6iqfje23k2f5 nrage.netwin.co.nz>, Regan Heath says...Not a bad idea. I prefer the solution I've mentioned a few times already. I just hope Walter gives us some indication of what he's thinking at some stage. (hint, hint) Regan On Wed, 29 Jun 2005 23:06:12 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:I would like to discuss one of my previous ideas again as it seems it was lost in the fire. I think below is the best compromise we can get. In fact as more I am looking on it as more I am sure that it not even compromise - it is "well done immutables". Idea is to extend typesystem with a new type: immutable (const, readonly) array and pointer. Proposed notation of immutable array type is as: typename#[] Proposed notation of immutable pointer is as: typename#* Immutable array as a type has exactly the same set of properties and methods as array except of mutators: opIndexAssign and int length(int newlength) Casting rules between array#[] and array[] are obvious: char#[] is1; char[] s1; is1 = s1; // ok. s1 = is1; // compile time (CT) err. Examples: s1[0] = 'a'; // ok is1[0] = 'a'; // CT err. s1.length = 1; // ok is1.length = 1; // CT err. -------------------------------- String and array literals are immutable by definition: char#[] slit1 = "Hello world"; // ok char[] s1 = "Hello world"; // CT err. Sidenote: In C++, by historical reasons, string literals have type char* and not const char* which is imho bad and needs to be changed. ------------------------------ This approach will give us readonlyness without major changes in language notation and architecture. This approach is free from C++ "const syntactical madness" where const is used for three different things and looks ugly sometimes. Clear differentiation of built-in reference types (array and struct) onto mutable and immutable versions will increase "fullness" of D's balanced type system. The thing is that char[] is from one side is atomic type and it is pretty natural to human to interpret it as just lets say atomic int. But at the same time it is a reference to some possibly shared data. This is why arrays and pointers shall exist in two forms. As a rule char[] is buffer/owner and char#[] is an immutable slice - consumer has no rights to change it as it will damage integrity state of the owner. ------------------------------------------- Possible variations of immutable type notation I've considered: 1) typename#[] 2) typename$[] 3) typename [] 4) typename[] const - not good as it conflicts with C++ cases visually. typename#[] probably is not the best variant of notation though. Ideas anyone? -------------------------------------------- I think it makes sense to add opSliceConst to the list of overloadable operators. -------------------------------------------- Having readonlyness interpreted and implemented this way will finally reconcile const and no-const camps. I hope. Andrew.
Jun 30 2005
Andrew Fedoniouk wrote:typename#[] probably is not the best variant of notation though. Ideas anyone? -------------------------------------------- I think it makes sense to add opSliceConst to the list of overloadable operators. -------------------------------------------- Having readonlyness interpreted and implemented this way will finally reconcile const and no-const camps. I hope. Andrew.
signify immutability though. I've never been opposed to longish names, so my vote would be for "immutable" as a decorator. immutable char[] is1; char[] s1; Brad
Jun 30 2005
"Brad Beveridge" <brad somewhere.net> wrote in message news:da13eo$1ao3$2 digitaldaemon.com...Andrew Fedoniouk wrote:typename#[] probably is not the best variant of notation though. Ideas anyone? -------------------------------------------- I think it makes sense to add opSliceConst to the list of overloadable operators. -------------------------------------------- Having readonlyness interpreted and implemented this way will finally reconcile const and no-const camps. I hope. Andrew.
signify immutability though. I've never been opposed to longish names, so my vote would be for "immutable" as a decorator. immutable char[] is1; char[] s1;
In fact immutable arrays are 80% or so of use cases of arrays in average code. So motivation is to make 'immutable' flag as shorter as possible. What about this: char![] Ideally, default char[] should be immutable and char![] should be mutable. Andrew.
Jun 30 2005
Andrew Fedoniouk wrote:"Brad Beveridge" <brad somewhere.net> wrote in message news:da13eo$1ao3$2 digitaldaemon.com...Andrew Fedoniouk wrote:typename#[] probably is not the best variant of notation though. Ideas anyone? -------------------------------------------- I think it makes sense to add opSliceConst to the list of overloadable operators. -------------------------------------------- Having readonlyness interpreted and implemented this way will finally reconcile const and no-const camps. I hope. Andrew.
I like it and I agree 100%. I don't happen to like # as the token to signify immutability though. I've never been opposed to longish names, so my vote would be for "immutable" as a decorator. immutable char[] is1; char[] s1;
In fact immutable arrays are 80% or so of use cases of arrays in average code. So motivation is to make 'immutable' flag as shorter as possible. What about this: char![] Ideally, default char[] should be immutable and char![] should be mutable. Andrew.
I agree that having a short flag is probably a good idea, but I would personally value absolute clarity over conciseness. Some other choices for "immutable" http://thesaurus.reference.com/search?q=immutable I like "fixed", "stable", "firm" and "solid" in that order. Of course, step 1 is getting Walter to agree that we need _something_ Brad
Jun 30 2005
Andrew Fedoniouk wrote:I would like to discuss one of my previous ideas again as it seems it was lost in the fire. I think below is the best compromise we can get. In fact as more I am looking on it as more I am sure that it not even compromise - it is "well done immutables". Idea is to extend typesystem with a new type: immutable (const, readonly) array and pointer.
immutable? Or does that open a can of worms that is too large? I think that perhaps they should be allowed to be decorated with "immutable", but I am not certain of the rules that should go along with it - ie, what members can be called etc. I don't really care about this, but it is good to be consistant. Of course, it will probably be a miracle if Walter gives us a straight answer on your original proposal even :) Brad
Jun 30 2005
"Brad Beveridge" <brad somewhere.net> wrote in message news:da1534$1cik$1 digitaldaemon.com...Andrew Fedoniouk wrote:I would like to discuss one of my previous ideas again as it seems it was lost in the fire. I think below is the best compromise we can get. In fact as more I am looking on it as more I am sure that it not even compromise - it is "well done immutables". Idea is to extend typesystem with a new type: immutable (const, readonly) array and pointer.
Or does that open a can of worms that is too large? I think that perhaps they should be allowed to be decorated with "immutable", but I am not certain of the rules that should go along with it - ie, what members can be called etc.
If it is needed anyone can create mutable/immutable state variable for his/her own class. Or create mutable versions of it. This approach was used in mango. A bit overkill, IMO, but works. This # stuff is needed because you cannot override behavior of basic types.I don't really care about this, but it is good to be consistant. Of course, it will probably be a miracle if Walter gives us a straight answer on your original proposal even :)
Hope dies last. And I think we are almost at position to start "Sic transit gloria mundi..."
Jun 30 2005
Just wanted to put in my vote for this suggested feature. Whatever the actual syntax ends up being (const / immutable / typename#[] / etc.), we definitely need this. It's up to Walter now, I guess. Cheers, --AJG. PS: Using hackish class-wrappers for this kind of thing is _way_ too much trouble and it not worth it IMHO. We need language/compiler level support. In article <da024r$65o$1 digitaldaemon.com>, Andrew Fedoniouk says...I would like to discuss one of my previous ideas again as it seems it was lost in the fire. I think below is the best compromise we can get. In fact as more I am looking on it as more I am sure that it not even compromise - it is "well done immutables". Idea is to extend typesystem with a new type: immutable (const, readonly) array and pointer. Proposed notation of immutable array type is as: typename#[] Proposed notation of immutable pointer is as: typename#* Immutable array as a type has exactly the same set of properties and methods as array except of mutators: opIndexAssign and int length(int newlength) Casting rules between array#[] and array[] are obvious: char#[] is1; char[] s1; is1 = s1; // ok. s1 = is1; // compile time (CT) err. Examples: s1[0] = 'a'; // ok is1[0] = 'a'; // CT err. s1.length = 1; // ok is1.length = 1; // CT err. -------------------------------- String and array literals are immutable by definition: char#[] slit1 = "Hello world"; // ok char[] s1 = "Hello world"; // CT err. Sidenote: In C++, by historical reasons, string literals have type char* and not const char* which is imho bad and needs to be changed. ------------------------------ This approach will give us readonlyness without major changes in language notation and architecture. This approach is free from C++ "const syntactical madness" where const is used for three different things and looks ugly sometimes. Clear differentiation of built-in reference types (array and struct) onto mutable and immutable versions will increase "fullness" of D's balanced type system. The thing is that char[] is from one side is atomic type and it is pretty natural to human to interpret it as just lets say atomic int. But at the same time it is a reference to some possibly shared data. This is why arrays and pointers shall exist in two forms. As a rule char[] is buffer/owner and char#[] is an immutable slice - consumer has no rights to change it as it will damage integrity state of the owner. ------------------------------------------- Possible variations of immutable type notation I've considered: 1) typename#[] 2) typename$[] 3) typename [] 4) typename[] const - not good as it conflicts with C++ cases visually. typename#[] probably is not the best variant of notation though. Ideas anyone? -------------------------------------------- I think it makes sense to add opSliceConst to the list of overloadable operators. -------------------------------------------- Having readonlyness interpreted and implemented this way will finally reconcile const and no-const camps. I hope. Andrew.
======================= I sync, therefore I am.
Jun 30 2005
On Thu, 30 Jun 2005 02:06:12 -0400, Andrew Fedoniouk <news terrainformatica.com> wrote:I would like to discuss one of my previous ideas again as it seems it was lost in the fire. I think below is the best compromise we can get. In fact as more I am looking on it as more I am sure that it not even compromise - it is "well done immutables". Idea is to extend typesystem with a new type: immutable (const, readonly) array and pointer. Proposed notation of immutable array type is as: typename#[] Proposed notation of immutable pointer is as: typename#*
I don't like it. Not just the syntax. I think immutable is so common that it should be the default. Right now we have to enforce it ourselves using COW. I don't have much of a problem with it but it seems many others do. What if arrays and pointers were immutable by default? The only way to make something mutable is to use a mutable keyword. I think it would be much more productive and sounds a lot more relaxing than specifying immutable. There would have to be a way to force something that is immutable to be mutable (?). Perhaps using cast(mutable char[]) for char[]. Here is an example: char[] foo = "hi"; // Good, immutable. mutable char[] bar = new char[30]; char[] baz = bar; // Mutable to immutable. mutable char[] bat = "hey"; // ERROR, string literal is immutable. mutable char[] qux = cast(mutable char[])bar; // Force immutable to mutable. Not recommended. It would break a lot of existing code, but I believe supporting the current style could still be supported using -deprecated. - Chris
Jun 30 2005
Vathix wrote:On Thu, 30 Jun 2005 02:06:12 -0400, Andrew Fedoniouk <news terrainformatica.com> wrote:
I don't like it. Not just the syntax. I think immutable is so common that it should be the default. Right now we have to enforce it ourselves using COW. I don't have much of a problem with it but it seems many others do.
- Chris
Would you still fall into the category of "we need _something_ to protect immutable data"? I think I might start a voting thread to see who need/want this feeture :) Brad
Jun 30 2005
On Thu, 30 Jun 2005 13:40:26 -0400, Brad Beveridge <brad somewhere.net> wrote:Would you still fall into the category of "we need _something_ to protect immutable data"?
No, but I'm willing to compromise.
Jun 30 2005
What is the difference between that and C++'s const as a type modifier?
C++:
typename const *
Proposal:
typename # *
Jun 30 2005
Walter wrote:What is the difference between that and C++'s const as a type modifier? C++: typename const * Proposal: typename # *
Or the other proposal, "readonly", seeing as how const is overloaded... (or the newly proposed variant thereof, which seems to be "immutable") BTW; There seems to be a lot of weird syntax lately: [$], !is and now char#[] Another note: There was an old suggestion (I think) that an explicit "in" would mean readonly for the array contents too, and not just for the array pointer. But it's a bit "unclear" for declarations, I think ? "in typename *" --anders
Jun 30 2005
Hi,Or the other proposal, "readonly", seeing as how const is overloaded... (or the newly proposed variant thereof, which seems to be "immutable")
The shorter the better, in my opinion. I prefer const or # over the other ones.BTW; There seems to be a lot of weird syntax lately: [$], !is and now char#[]
I agree, but I don't think it's a bad thing at all. The more the merrier, I say. Oh, and what is [$]? I've never seen that one before...Another note: There was an old suggestion (I think) that an explicit "in" would mean readonly for the array contents too, and not just for the array pointer.
I like this a lot. This is the way it should be, IMHO, by default at all times; at least the explicit "in" would give us the option to enforce it. I can't decide which one I like better, the explicit in or immutability; either one would be a great improvement. I guess both would be even better? Cheers, --AJG. ======================= I sync, therefore I am.
Jun 30 2005
AJG wrote:Oh, and what is [$]? I've never seen that one before...
"length", for arrays. As in this "remove": array = array[0 .. i-1] ~ array[i+1 .. $]; --anders
Jun 30 2005
Awesome, thanks. I use length a lot, so $ is great. Anybody have any concerns about this usage?: // Easy way to get last element. int lastItem = someArray[--$]; Cheers, --AJG. In article <da1q3p$26jr$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...AJG wrote:Oh, and what is [$]? I've never seen that one before...
"length", for arrays. As in this "remove": array = array[0 .. i-1] ~ array[i+1 .. $]; --anders
======================== if (!sin) throw rock[0];
Jun 30 2005
On Fri, 1 Jul 2005 02:46:41 +0000 (UTC), AJG <AJG_member pathlink.com> wrote:Awesome, thanks. I use length a lot, so $ is great. Anybody have any concerns about this usage?: // Easy way to get last element. int lastItem = someArray[--$];
And pull it off, so to speak (you're decrementing the length, or trying to). Does that work? AFAIK you cannot say "--someArray.length" as length is a property i.e not an lvalue I write someArray[$-1] to get the last element. ReganCheers, --AJG. In article <da1q3p$26jr$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...AJG wrote:Oh, and what is [$]? I've never seen that one before...
"length", for arrays. As in this "remove": array = array[0 .. i-1] ~ array[i+1 .. $]; --anders
======================== if (!sin) throw rock[0];
Jun 30 2005
I write someArray[$-1] to get the last element.
Personally, I think using # is way more descriptive than $... $ looks like a php variable.. some might say # looks like a cold fusion varaible, but honestly, cold fusion is crap, so I just ignore it... # also seems like "number of elements"... $ has no other natural meaning... list[# - 5 .. #] should give you the last 5 elements of the array. Also, I have another idea. using "..." should mean, to the end. so list[4 ...] means, from 4 on. so... list[# - 5 ...] means, the last 5 :) Just an idea. Won't break existing code. -- Thanks, Trevor Parscal www.trevorparscal.com trevorparscal hotmail.com
Jul 05 2005
Hi, In article <daf0km$umn$1 digitaldaemon.com>, Trevor Parscal says...I write someArray[$-1] to get the last element.
like a php variable.. some might say # looks like a cold fusion varaible, but honestly, cold fusion is crap, so I just ignore it... # also seems like "number of elements"... $ has no other natural meaning... list[# - 5 .. #] should give you the last 5 elements of the array.
You have my vote. I agree wholeheartedly.Also, I have another idea. using "..." should mean, to the end. so list[4 ...] means, from 4 on. so... list[# - 5 ...] means, the last 5 :) Just an idea. Won't break existing code.
I also like this idea. To make it simpler we could just use .. and leave one (or both) of the ends blank. So that: array[a ..] == array[a .. #]; array[.. b] == array[0 .. b]; array[..] == array[0 .. #] == array; Just thinking out loud. --AJG.-- Thanks, Trevor Parscal www.trevorparscal.com trevorparscal hotmail.com
Jul 05 2005
On Wed, 6 Jul 2005 01:05:17 +0000 (UTC), AJG <AJG_member pathlink.com> wrote:In article <daf0km$umn$1 digitaldaemon.com>, Trevor Parscal says...I write someArray[$-1] to get the last element.
like a php variable.. some might say # looks like a cold fusion varaible, but honestly, cold fusion is crap, so I just ignore it... # also seems like "number of elements"... $ has no other natural meaning... list[# - 5 .. #] should give you the last 5 elements of the array.
You have my vote. I agree wholeheartedly.
I dont mind $, that said, I don't mind # either.Also, I have another idea. using "..." should mean, to the end. so list[4 ...] means, from 4 on. so... list[# - 5 ...] means, the last 5 :) Just an idea. Won't break existing code.
I also like this idea. To make it simpler we could just use .. and leave one (or both) of the ends blank. So that: array[a ..] == array[a .. #]; array[.. b] == array[0 .. b]; array[..] == array[0 .. #] == array; Just thinking out loud.
This idea has been proposed before, along with many others. Do a search, you'll see what I mean. Regan
Jul 05 2005
On Thu, 30 Jun 2005 11:19:38 -0700, Walter <newshound digitalmars.com> wrote:What is the difference between that and C++'s const as a type modifier? C++: typename const * Proposal: typename # *
Nothing, which is why I prefer the idea I've been bandying (sp?) around here for the past month. Please read carefully this is _not_ the same thing. A readonly compile time, and perhaps also runtime (disabled for -release) readonly bit flag for all variables. Initialised to 'false'. Set to 'true' in the presence of "readonly" as a type modifier. Set to 'true' when passed as an 'in' parameter. Compiler errors on all operations that mutate a readonly flagged variable. Example usage: class Foo { char[] data; readonly char[] get() { return data; } } void foo(inout char[] data) { data[0] = 'a'; } Foo f = new Foo(); char[] p = f.get(); p[0] = 'a'; //error cannot mutate readonly foo(p); //error passing readonly as mutable void foo(char[] data) { data[0] = 'a'; } //error cannot mutate readonly IMPORTANT: this does not create a seperate distinct type, "readonly char[]" is not a different type to "char[]" it's the same type with it's readonly flag set to 'true'. The reason this is important is that it stops this situation... char[] s; ..s used as temp var here.. readonly char[] p = f.get(); s = p; //error s is not readonly Which is just plain irritating. People typically solve the above by casting the readonly away. Not good. In the above 's's readonly flag is set on assignment, it becomes readonly. The readonly flag would be set to false when passed as 'out', or on assignment to a rhs which has readonly=false (including null). A runtime flag is required for cases like: char[] p = test ? some_string : f.get(); p[1] = 'd'; //is 'p' readonly if some_string isn't? where the compiler cannot tell at compile time. The runtime flag would be present in every single variable, disabled by -release and/or it's own compile time flag (perhaps disabled by default like -unittest) Regan
Jun 30 2005
Regan, Readonly flag is technicaly difficult and inefficient to implement. Any access to the pointer(sic!) and array shall check first this flag in runtime. Second problem is that you need to store somewhere this bit. Where? Proposed solution is just static (compile time) test. Moving conditions which can be checked in compile to runtime is generally not a good idea - non-efficient and difficult to verify in full. To be short, in runtime you may get following: <quote> Ariane 5 Rocket Disaster The Ariane 5 Rocket was made by the European Space Agency. In simple terms Navigational software was used from the Ariane 4 in the more powerful Ariane 5. The computer was programmed with a safety feature which aborted the mission and caused the rocket to self destruct if it went off course. Due to an error in the navigation calculations, however, the Arian 5 self destructed - even though it was on course to its planned destination. Investigators later discovered that the cause of the Ariane 5 disaster was attributed to calculations based on the Ariane 4 dimensions and power. </quote> If it is possible to verify conditions in CT you'd better do it there. PS: Ariane software is written in ADA, afaik. Andrew. "Regan Heath" <regan netwin.co.nz> wrote in message news:opss7fh6dr23k2f5 nrage.netwin.co.nz...On Thu, 30 Jun 2005 11:19:38 -0700, Walter <newshound digitalmars.com> wrote:What is the difference between that and C++'s const as a type modifier? C++: typename const * Proposal: typename # *
Nothing, which is why I prefer the idea I've been bandying (sp?) around here for the past month. Please read carefully this is _not_ the same thing. A readonly compile time, and perhaps also runtime (disabled for -release) readonly bit flag for all variables. Initialised to 'false'. Set to 'true' in the presence of "readonly" as a type modifier. Set to 'true' when passed as an 'in' parameter. Compiler errors on all operations that mutate a readonly flagged variable. Example usage: class Foo { char[] data; readonly char[] get() { return data; } } void foo(inout char[] data) { data[0] = 'a'; } Foo f = new Foo(); char[] p = f.get(); p[0] = 'a'; //error cannot mutate readonly foo(p); //error passing readonly as mutable void foo(char[] data) { data[0] = 'a'; } //error cannot mutate readonly IMPORTANT: this does not create a seperate distinct type, "readonly char[]" is not a different type to "char[]" it's the same type with it's readonly flag set to 'true'. The reason this is important is that it stops this situation... char[] s; ..s used as temp var here.. readonly char[] p = f.get(); s = p; //error s is not readonly Which is just plain irritating. People typically solve the above by casting the readonly away. Not good. In the above 's's readonly flag is set on assignment, it becomes readonly. The readonly flag would be set to false when passed as 'out', or on assignment to a rhs which has readonly=false (including null). A runtime flag is required for cases like: char[] p = test ? some_string : f.get(); p[1] = 'd'; //is 'p' readonly if some_string isn't? where the compiler cannot tell at compile time. The runtime flag would be present in every single variable, disabled y -release and/or it's own compile time flag (perhaps disabled by default like -unittest) Regan
Jun 30 2005
On Thu, 30 Jun 2005 19:52:53 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:Readonly flag is technicaly difficult and inefficient to implement.
The runtime or the compile time one? (you seem not to realise I am talking about *both*)Any access to the pointer(sic!) and array shall check first this flag in runtime.
Yes. When you enable the runtime DBC feature you'll get this, just like array bounds checks.Second problem is that you need to store somewhere this bit. Where?
1 bit in every single variable.Proposed solution is just static (compile time) test.
Mine is first a compile time suggestion, followed by a runtime one (as it's been shown that some cases exist where compile time check is impossible)Moving conditions which can be checked in compile to runtime is generally not a good idea - non-efficient and difficult to verify in full.
Like I said above, my primary suggestion is a compile time one, it has been shown not all cases can be verified at compile time, as such a runtime solution is required.To be short, in runtime you may get following:
<snip> I can't see how this is even relevant. ReganAndrew. "Regan Heath" <regan netwin.co.nz> wrote in message news:opss7fh6dr23k2f5 nrage.netwin.co.nz...On Thu, 30 Jun 2005 11:19:38 -0700, Walter <newshound digitalmars.com> wrote:What is the difference between that and C++'s const as a type modifier? C++: typename const * Proposal: typename # *
Nothing, which is why I prefer the idea I've been bandying (sp?) around here for the past month. Please read carefully this is _not_ the same thing. A readonly compile time, and perhaps also runtime (disabled for -release) readonly bit flag for all variables. Initialised to 'false'. Set to 'true' in the presence of "readonly" as a type modifier. Set to 'true' when passed as an 'in' parameter. Compiler errors on all operations that mutate a readonly flagged variable. Example usage: class Foo { char[] data; readonly char[] get() { return data; } } void foo(inout char[] data) { data[0] = 'a'; } Foo f = new Foo(); char[] p = f.get(); p[0] = 'a'; //error cannot mutate readonly foo(p); //error passing readonly as mutable void foo(char[] data) { data[0] = 'a'; } //error cannot mutate readonly IMPORTANT: this does not create a seperate distinct type, "readonly char[]" is not a different type to "char[]" it's the same type with it's readonly flag set to 'true'. The reason this is important is that it stops this situation... char[] s; ..s used as temp var here.. readonly char[] p = f.get(); s = p; //error s is not readonly Which is just plain irritating. People typically solve the above by casting the readonly away. Not good. In the above 's's readonly flag is set on assignment, it becomes readonly. The readonly flag would be set to false when passed as 'out', or on assignment to a rhs which has readonly=false (including null). A runtime flag is required for cases like: char[] p = test ? some_string : f.get(); p[1] = 'd'; //is 'p' readonly if some_string isn't? where the compiler cannot tell at compile time. The runtime flag would be present in every single variable, disabled y -release and/or it's own compile time flag (perhaps disabled by default like -unittest) Regan
Jun 30 2005
"Regan Heath" <regan netwin.co.nz> wrote in message news:opss7xxlgs23k2f5 nrage.netwin.co.nz...On Thu, 30 Jun 2005 19:52:53 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:Readonly flag is technicaly difficult and inefficient to implement.
The runtime or the compile time one? (you seem not to realise I am talking about *both*)Any access to the pointer(sic!) and array shall check first this flag in runtime.
Yes. When you enable the runtime DBC feature you'll get this, just like array bounds checks.Second problem is that you need to store somewhere this bit. Where?
1 bit in every single variable.
The question is: where this bit is located? array variable is 32bit ptr (64bit) and 32bit (64bit) length. pointer variable is 32bit (64bit). So where is the place for it? In additional machine word which will be assosiated with each variable?Proposed solution is just static (compile time) test.
Mine is first a compile time suggestion, followed by a runtime one (as it's been shown that some cases exist where compile time check is impossible)Moving conditions which can be checked in compile to runtime is generally not a good idea - non-efficient and difficult to verify in full.
Like I said above, my primary suggestion is a compile time one, it has been shown not all cases can be verified at compile time, as such a runtime solution is required.
Universal solution is to have opAssign, etc. So extreme cases can be handled by declaring your own structures/classes. Having hidden bit (if it is possible at all) for only arrays and pointers is little bit unnatural, imho.To be short, in runtime you may get following:
<snip> I can't see how this is even relevant. ReganAndrew. "Regan Heath" <regan netwin.co.nz> wrote in message news:opss7fh6dr23k2f5 nrage.netwin.co.nz...On Thu, 30 Jun 2005 11:19:38 -0700, Walter <newshound digitalmars.com> wrote:What is the difference between that and C++'s const as a type modifier? C++: typename const * Proposal: typename # *
Nothing, which is why I prefer the idea I've been bandying (sp?) around here for the past month. Please read carefully this is _not_ the same thing. A readonly compile time, and perhaps also runtime (disabled or -release) readonly bit flag for all variables. Initialised to 'false'. Set to 'true' in the presence of "readonly" as a type modifier. Set to 'true' when passed as an 'in' parameter. Compiler errors on all operations that mutate a readonly flagged variable. Example usage: class Foo { char[] data; readonly char[] get() { return data; } } void foo(inout char[] data) { data[0] = 'a'; } Foo f = new Foo(); char[] p = f.get(); p[0] = 'a'; //error cannot mutate readonly foo(p); //error passing readonly as mutable void foo(char[] data) { data[0] = 'a'; } //error cannot mutate readonly IMPORTANT: this does not create a seperate distinct type, "readonly char[]" is not a different type to "char[]" it's the same type with it's readonly flag set to 'true'. The reason this is important is that it stops this situation... char[] s; ..s used as temp var here.. readonly char[] p = f.get(); s = p; //error s is not readonly Which is just plain irritating. People typically solve the above by casting the readonly away. Not good. In the above 's's readonly flag is set on assignment, it becomes readonly. The readonly flag would be set to false when passed as 'out', or on assignment to a rhs which has readonly=false (including null). A runtime flag is required for cases like: char[] p = test ? some_string : f.get(); p[1] = 'd'; //is 'p' readonly if some_string isn't? where the compiler cannot tell at compile time. The runtime flag would be present in every single variable, disabled y -release and/or it's own compile time flag (perhaps disabled by default like -unittest) Regan
Jun 30 2005
On Thu, 30 Jun 2005 23:10:00 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:"Regan Heath" <regan netwin.co.nz> wrote in message news:opss7xxlgs23k2f5 nrage.netwin.co.nz...On Thu, 30 Jun 2005 19:52:53 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:Readonly flag is technicaly difficult and inefficient to implement.
The runtime or the compile time one? (you seem not to realise I am talking about *both*)Any access to the pointer(sic!) and array shall check first this flag in runtime.
Yes. When you enable the runtime DBC feature you'll get this, just like array bounds checks.Second problem is that you need to store somewhere this bit. Where?
1 bit in every single variable.
The question is: where this bit is located? array variable is 32bit ptr (64bit) and 32bit (64bit) length. pointer variable is 32bit (64bit). So where is the place for it? In additional machine word which will be assosiated with each variable?
If that is what is required, yes.Proposed solution is just static (compile time) test.
Mine is first a compile time suggestion, followed by a runtime one (as it's been shown that some cases exist where compile time check is impossible)Moving conditions which can be checked in compile to runtime is generally not a good idea - non-efficient and difficult to verify in full.
Like I said above, my primary suggestion is a compile time one, it has been shown not all cases can be verified at compile time, as such a runtime solution is required.
Universal solution is to have opAssign, etc.
That doesn't give us immutable char[].So extreme cases can be handled by declaring your own structures/classes. Having hidden bit (if it is possible at all) for only arrays and pointers is little bit unnatural, imho.
Not just arrays and pointers, everything, even UDT's. Regan
Jun 30 2005
"Regan Heath" <regan netwin.co.nz> wrote in message news:opss714rpw23k2f5 nrage.netwin.co.nz...On Thu, 30 Jun 2005 23:10:00 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:"Regan Heath" <regan netwin.co.nz> wrote in message news:opss7xxlgs23k2f5 nrage.netwin.co.nz...On Thu, 30 Jun 2005 19:52:53 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:Readonly flag is technicaly difficult and inefficient to implement.
The runtime or the compile time one? (you seem not to realise I am talking about *both*)Any access to the pointer(sic!) and array shall check first this flag in runtime.
Yes. When you enable the runtime DBC feature you'll get this, just like array bounds checks.Second problem is that you need to store somewhere this bit. Where?
1 bit in every single variable.
The question is: where this bit is located? array variable is 32bit ptr (64bit) and 32bit (64bit) length. pointer variable is 32bit (64bit). So where is the place for it? In additional machine word which will be assosiated with each variable?
If that is what is required, yes.
So -release will have sizeof(void*) == 32 and otherwise sizeof(void*) == 64. Do you *really* think this is a solution?Proposed solution is just static (compile time) test.
Mine is first a compile time suggestion, followed by a runtime one (as it's been shown that some cases exist where compile time check is impossible)Moving conditions which can be checked in compile to runtime is generally not a good idea - non-efficient and difficult to verify in full.
Like I said above, my primary suggestion is a compile time one, it has been shown not all cases can be verified at compile time, as such a runtime solution is required.
Universal solution is to have opAssign, etc.
That doesn't give us immutable char[].
It will give you an option: struct chars { private char[] data; bit mutableBit; void opAssign(chars rightSide) { if(!mutableBit) throw new WellKnownAndExpectedExceptionAndNotAnError; ... } }So extreme cases can be handled by declaring your own structures/classes. Having hidden bit (if it is possible at all) for only arrays and pointers is little bit unnatural, imho.
Not just arrays and pointers, everything, even UDT's. Regan
Jul 01 2005
On Fri, 1 Jul 2005 00:35:38 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:1 bit in every single variable.
The question is: where this bit is located? array variable is 32bit ptr (64bit) and 32bit (64bit) length. pointer variable is 32bit (64bit). So where is the place for it? In additional machine word which will be assosiated with each variable?
If that is what is required, yes.
So -release will have sizeof(void*) == 32 and otherwise sizeof(void*) == 64. Do you *really* think this is a solution?
Yes. Almost all cases are handled at *compile* time, there are very few cases which cannot be handled at compile time. As such the runtime solution is a very small piece of the overall solution. It's optional, can be disabled by a switch, and would *only* be used during the design stage just like the other DBC features.Proposed solution is just static (compile time) test.
Mine is first a compile time suggestion, followed by a runtime one (as it's been shown that some cases exist where compile time check is impossible)Moving conditions which can be checked in compile to runtime is generally not a good idea - non-efficient and difficult to verify in full.
Like I said above, my primary suggestion is a compile time one, it has been shown not all cases can be verified at compile time, as such a runtime solution is required.
Universal solution is to have opAssign, etc.
That doesn't give us immutable char[].
It will give you an option: struct chars { private char[] data; bit mutableBit; void opAssign(chars rightSide) { if(!mutableBit) throw new WellKnownAndExpectedExceptionAndNotAnError; ... } }
D does not need a string class. Regan
Jul 01 2005
I recently forgot my 'other' option for runtime 'readonly' checking of
"in" parameters, this solution uses in/out contracts, eg.
import std.stdio;
import std.string;
import std.c.stdlib;
void main()
{
char[] a = "regan";
foo(a);
}
void* cmp = null;
void foo(char[] string)
in {
cmp = realloc(cmp,string.sizeof);
memcpy(cmp,&string,string.sizeof);
}
out {
assert(memcmp(cmp,&string,string.sizeof) == 0);
}
body {
//this causes the assert, remove it, no assert.
string.length = 20;
}
As you can see it simply makes a duplicate of the 'in' parameter then
compares the parameter with the duplicate upon completion of the function.
This is better than a readonly flag in every object as it saves memory
overall. It is worse in that it doesn't tell you exactly where it was
modified, just that it was modified somewhere in that function.
This idea doesn't necessarily help us with "const" labelled returns eg.
class Foo {
private char[] data;
const char[] get() { return data[0..5]; }
}
char[] p = f.get();
char[] s = b ? p : "foo"; //where b is determined at runtime.
s[0] = 'a';
However a copy could be setup when f.get() returned and checked when 'p'
went out of scope. This sounds difficult ot implement to me however.
Regan
On Fri, 01 Jul 2005 19:46:23 +1200, Regan Heath <regan netwin.co.nz> wrote:
On Fri, 1 Jul 2005 00:35:38 -0700, Andrew Fedoniouk
<news terrainformatica.com> wrote:
1 bit in every single variable.
The question is: where this bit is located?
array variable is 32bit ptr (64bit) and 32bit (64bit) length.
pointer variable is 32bit (64bit). So where is the place for it?
In additional machine word which will be assosiated with
each variable?
If that is what is required, yes.
So -release will have sizeof(void*) == 32
and otherwise sizeof(void*) == 64.
Do you *really* think this is a solution?
Yes.
Almost all cases are handled at *compile* time, there are very few cases
which cannot be handled at compile time.
As such the runtime solution is a very small piece of the overall
solution. It's optional, can be disabled by a switch, and would *only*
be used during the design stage just like the other DBC features.
Proposed solution is just static (compile time) test.
Mine is first a compile time suggestion, followed by a runtime one
(as
it's been shown that some cases exist where compile time check is
impossible)
Moving conditions which can be checked in compile to runtime
is generally not a good idea - non-efficient and difficult
to verify in full.
Like I said above, my primary suggestion is a compile time one, it
has
been shown not all cases can be verified at compile time, as such a
runtime solution is required.
Universal solution is to have opAssign, etc.
That doesn't give us immutable char[].
It will give you an option:
struct chars {
private char[] data;
bit mutableBit;
void opAssign(chars rightSide)
{
if(!mutableBit)
throw new WellKnownAndExpectedExceptionAndNotAnError;
...
}
}
D does not need a string class.
Regan
Jul 01 2005
"Walter" <newshound digitalmars.com> wrote in message news:da1d5u$1kdf$1 digitaldaemon.com...What is the difference between that and C++'s const as a type modifier? C++: typename const * Proposal: typename # *
typename # * is eqiuvalent of C++'s const typename * -or- typename const * It is a 'mutable pointer to immutable data.' I think that proposed singular form typename #* where '#' means 'no = ' is a bit better. But again it is a personal matter. Andrew.
Jun 30 2005
"Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:da024r$65o$1 digitaldaemon.com...I would like to discuss one of my previous ideas again as it seems it was lost in the fire.
I've been discussing this issue with Andrei (of Modern C++ Design fame). He points out that there are numerous different "const" semantics, each having their uses and disadvantages. He suggests that all should be supported in one way or another, and I agree that that would have some advantages. One of my (several) dislikes with "const" is that most (90% ?) of a function's parameters are likely to be "const". So one winds up with the C++ aesthetically ugly consequence of "const" here, there, everywhere. And you can't use it casually here and there, once you start down the road of making a few functions have "const" parameters, you've got to do it throughout the program. So perhaps one could turn that inside out, and make "const" the default for function parameters. If the parameter was to be changed, it'd be explicitly marked as "mutable" or some such. But that runs into another problem. Function local variables, on the other hand, one would want to be "mutable" by default. There's also the issue that "const" already exists as a variable storage class. So far, I haven't thought of anything that makes consistent sense, and doesn't look like an ugly hack. One thing I have thought of is a compromise. Change the semantics of explicitly "in" parameters to be what Andrei calls "deep immutable". Deep immutable parameters would have unchanging values for the scope of that parameter, and also every sub-object reachable by that parameter would also be unchangeable. The values wouldn't change even by another reference or another thread. (This is quite unlike C++ "const".) "in" would be a promise by the programmer, and could not be guaranteed by the compiler - but - the optimizer can take advantage of this promise to generate perhaps significantly better code. (With C++ "const", values can change at any momen t by another reference or another thread, making optimizations based on "const" impossible.) C++ "const" is enforced by the compiler, but is useless semantic information. "in" is not enforced by the compiler beyond the trivial, but is useful semantic information.
Jul 01 2005
On Fri, 1 Jul 2005 01:34:31 -0700, Walter <newshound digitalmars.com> wrote:But that runs into another problem. Function local variables, on the other hand, one would want to be "mutable" by default.
By function local do you mean "a" or "b" below? void foo(char[] a) { char[] b; } Regan
Jul 01 2005
I think he means "b". As opposed to parameter in variables, like "a". --AJG. In article <opss8aohii23k2f5 nrage.netwin.co.nz>, Regan Heath says...On Fri, 1 Jul 2005 01:34:31 -0700, Walter <newshound digitalmars.com> wrote:But that runs into another problem. Function local variables, on the other hand, one would want to be "mutable" by default.
By function local do you mean "a" or "b" below? void foo(char[] a) { char[] b; } Regan
Jul 01 2005
If he does, then why can't all 'in' parameters be immutable. 'in' is the
default parameter type, so all variables would be immutable by default. No
'const' (or whatever keyword is used) everywhere. I've always thought 'in'
was part of the function contract stating "I only need read access to
this", this change would actually enforce that.
If a mutable copy was required then:
void foo(char[] a)
{
char[] b = a.dup;
}
would work. It could even be optimised by the compiler. I imagine the
compiler is already making a dup of the variable which is passed (as it
does for value types), this would make a second one, it could optimise one
of those duplicates away.
Regan
On Fri, 1 Jul 2005 13:20:18 +0000 (UTC), AJG <AJG_member pathlink.com>
wrote:
I think he means "b". As opposed to parameter in variables, like "a".
--AJG.
In article <opss8aohii23k2f5 nrage.netwin.co.nz>, Regan Heath says...
On Fri, 1 Jul 2005 01:34:31 -0700, Walter <newshound digitalmars.com>
wrote:
But that runs into another problem. Function local variables, on the
other hand, one would want to be "mutable" by default.
By function local do you mean "a" or "b" below?
void foo(char[] a)
{
char[] b;
}
Regan
Jul 01 2005
Hi,One of my (several) dislikes with "const" is that most (90% ?) of a function's parameters are likely to be "const". So one winds up with the C++ aesthetically ugly consequence of "const" here, there, everywhere. And you can't use it casually here and there, once you start down the road of making a few functions have "const" parameters, you've got to do it throughout the program.
Very true.One thing I have thought of is a compromise. Change the semantics of explicitly "in" parameters to be what Andrei calls "deep immutable". Deep immutable parameters would have unchanging values for the scope of that parameter, and also every sub-object reachable by that parameter would also be unchangeable.
This would be fantastic, IMHO. It makes perfect sense, and we get the best of both worlds. [a] Immutable variables exactly where we need them; and [b] the simple aesthetic syntax. This should have always been the default, and it definitely gets my vote by far. Cheers, --AJG. ======================= I sync, therefore I am.
Jul 01 2005
In article <da2v7t$b9b$1 digitaldaemon.com>, Walter says...One thing I have thought of is a compromise. Change the semantics of explicitly "in" parameters to be what Andrei calls "deep immutable". Deep immutable parameters would have unchanging values for the scope of that parameter, and also every sub-object reachable by that parameter would also be unchangeable. The values wouldn't change even by another reference or another thread. (This is quite unlike C++ "const".) "in" would be a promise by the programmer, and could not be guaranteed by the compiler - but - the optimizer can take advantage of this promise to generate perhaps significantly better code. (With C++ "const", values can change at any momen t by another reference or another thread, making optimizations based on "const" impossible.)
This sounds great. In this scenario, can I store the in object (or its sub objects) to a local variable? If so it would be immutable too I would guess, but is there a special syntax? (Or is slicing, etc forbidden in these cases?) :void foo(in int[] x) :{ : int[] middle1 = x[1..$-1]; // is middle implicitely immutable? : in int[] middle2 = x[1..$-1]; // explicitly marked as immutable? : middle[0] = middle1[1]; // this should fail to compile right? :}C++ "const" is enforced by the compiler, but is useless semantic information. "in" is not enforced by the compiler beyond the trivial, but is useful semantic information.
Kevin
Jul 01 2005
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message news:da3ppb$1h97$1 digitaldaemon.com...This sounds great. In this scenario, can I store the in object (or its
objects) to a local variable? If so it would be immutable too I would
but is there a special syntax? (Or is slicing, etc forbidden in these
:void foo(in int[] x) :{ : int[] middle1 = x[1..$-1]; // is middle implicitely immutable?
I don't see how to make that work right. The only thing I can think of is to allow middle1 to modify x, but that such modification would be undefined behavior. Not so hot.: in int[] middle2 = x[1..$-1]; // explicitly marked as immutable?
There I hate using 'in' as a storage class. It's confusing with 'const'.: middle[0] = middle1[1]; // this should fail to compile right?
Yes. That's one case the compiler should pick up.
Jul 01 2005
In article <da3ug1$1n4l$1 digitaldaemon.com>, Walter says..."Kevin Bealer" <Kevin_member pathlink.com> wrote in message news:da3ppb$1h97$1 digitaldaemon.com...This sounds great. In this scenario, can I store the in object (or its
objects) to a local variable? If so it would be immutable too I would
but is there a special syntax? (Or is slicing, etc forbidden in these
:void foo(in int[] x) :{ : int[] middle1 = x[1..$-1]; // is middle implicitely immutable?
I don't see how to make that work right. The only thing I can think of is to allow middle1 to modify x, but that such modification would be undefined behavior. Not so hot.
I think in this case a copy would need to be made. ie. int[] middle1 = x[1..$-1].dup; This is no different than when a programmer wants to modify a const parameter in C++. I'm not sure that there's a good way to enforce this in the compiler, though it might be nice if there were a way to verify that a parameter is unchanged via DBC. Perhaps something like this? void fn( in int[] x ) in { preserve int[] p = x.dup; } out { assert( x == p ); } or perhaps: void fn( in int[] x ) int[] p; in { p = x.dup; } .. Sean
Jul 01 2005
Walter escribió:One thing I have thought of is a compromise. Change the semantics of explicitly "in" parameters to be what Andrei calls "deep immutable". Deep immutable parameters would have unchanging values for the scope of that parameter, and also every sub-object reachable by that parameter would also be unchangeable. The values wouldn't change even by another reference or another thread. (This is quite unlike C++ "const".) "in" would be a promise by the programmer, and could not be guaranteed by the compiler - but - the optimizer can take advantage of this promise to generate perhaps significantly better code. (With C++ "const", values can change at any momen t by another reference or another thread, making optimizations based on "const" impossible.)
I think that's similar to what Pascal does, and that's something I agree with. One point that isn't addressed yet (I think) is returning something: can it be modified? What happens if it's modified? etc. -- Carlos Santander Bernal
Jul 01 2005
"Carlos Santander" <csantander619 gmail.com> wrote in message news:da4e0i$27v9$1 digitaldaemon.com...One point that isn't addressed yet (I think) is returning something: can it be modified? What happens if it's modified? etc.
With the 'in' compromise, it doesn't address return values.
Jul 02 2005
"Walter" <newshound digitalmars.com> wrote in message news:da2v7t$b9b$1 digitaldaemon.com..."Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:da024r$65o$1 digitaldaemon.com...I would like to discuss one of my previous ideas again as it seems it was lost in the fire.
So far, I haven't thought of anything that makes consistent sense, and doesn't look like an ugly hack. One thing I have thought of is a compromise. Change the semantics of explicitly "in" parameters to be what Andrei calls "deep immutable". Deep immutable parameters would have unchanging values for the scope of that parameter, and also every sub-object reachable by that parameter would also be unchangeable. The values wouldn't change even by another reference or another thread. (This is quite unlike C++ "const".) "in" would be a promise by the programmer, and could not be guaranteed by the compiler - but - the optimizer can take advantage of this promise to generate perhaps significantly better code. (With C++ "const", values can change at any momen t by another reference or another thread, making optimizations based on "const" impossible.)
One other thought - Make it so that an "explicit in" makes a copy as it does now, and the default (non-specified) param. storage class is "deep immutable". Pointer params would act the same as they do now regardless, and functions with extern(...) would be exempt as well. If pointers were taken out of the picture, why couldn't the compiler catch cases like below? class C { ... } void foo(C c, int[] arr) { // Errors c = new C; c.i = 10; int* z = &c.i; bar(c); C x = c; arr = new int[20]; arr[10] = 10; arr[] = 0; int[] b = arr; int[] b4 = arr[0..10]; int* y = &a[5]; // Ok int[] b2 = arr.dup; int[] b3 = arr[]; int[] b5 = arr[0..10].dup; int* p = cast(int*)&a[6]; void* v = cast(void*)&a[6]; *(cast(int*)v) = 700; baz(c); } void bar(inout C x) { ... } void baz(C x) { ... } In all those cases either the param is directly an lvalue /or/ the address of the param is directly taken, or the same for a member of an aggregate. The spec. would explicitly say "the compiler is responsible for checking /only/ for cases where "either the param (or one of it's aggragate members) is directly assigned to, the address of the param (or one of its aggragate members) is directly taken or the param (or an aggregate member) is directly passed into a function via an out or inout parameter. All other cases are undefined."
Jul 02 2005
"Walter" <newshound digitalmars.com> wrote in message news:da2v7t$b9b$1 digitaldaemon.com..."Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:da024r$65o$1 digitaldaemon.com...I would like to discuss one of my previous ideas again as it seems it was lost in the fire.
I've been discussing this issue with Andrei (of Modern C++ Design fame). He points out that there are numerous different "const" semantics, each having their uses and disadvantages. He suggests that all should be supported in one way or another, and I agree that that would have some advantages. One of my (several) dislikes with "const" is that most (90% ?) of a function's parameters are likely to be "const". So one winds up with the C++ aesthetically ugly consequence of "const" here, there, everywhere. And you can't use it casually here and there, once you start down the road of making a few functions have "const" parameters, you've got to do it throughout the program. So perhaps one could turn that inside out, and make "const" the default for function parameters. If the parameter was to be changed, it'd be explicitly marked as "mutable" or some such. But that runs into another problem. Function local variables, on the other hand, one would want to be "mutable" by default. There's also the issue that "const" already exists as a variable storage class.
I guess I don't understand why this is a problem because there has always been a 'seperation' and distinction between locals and params to me. I realize there is a union of scope inside the function and they share many of the same syntax and semantic rules as variables, but I've always considered them two seperate and distinct groups of vars. I think most non-newbie programmers realize this and recognize that any params passed by reference also 'live' outside of the function. Why do you think a typical programmer would be completely put off by the idea that an 'implicit in' param couldn't be modified, while by default a local variable could (especially if the compiler would constantly reinforce the idea that "hey - D's default params are different" by reporting trivial-case errors)? Thanks, - Dave
Jul 04 2005









Victor Nakoryakov <nail-mail mail.ru> 