digitalmars.D - inout/out static array parameter
- Tom (12/12) Feb 21 2006 Why is this illegal? Where does the documentation states this?
- Derek Parnell (19/30) Feb 21 2006 I cannot see why D should be upset with this. The implementation would b...
- Regan Heath (34/61) Feb 21 2006 Not quite, when you pass something as 'in' you always get a copy of it, ...
- Derek Parnell (45/104) Feb 21 2006 I don't believe that to be entirely accurate. For example, if you pass a...
- Regan Heath (5/8) Feb 21 2006 Arrays are passed as references (AKA "array reference"). Passing a
- Regan Heath (64/157) Feb 22 2006 My knowledge of assembler is practically non existant. Does the 'mov' co...
- Regan Heath (13/24) Feb 22 2006 No threads required to proove aliasing.
- Tom (23/51) Feb 22 2006 This isn't true:
- Regan Heath (26/85) Feb 22 2006 Yes, it is. The key is realising what it is you're actually passing, in ...
- Tom (19/109) Feb 22 2006 I know, I thought you meant that 'in' makes a copy of the whole array, n...
- Derek Parnell (7/17) Feb 22 2006 Yes, they were my own words. You won't find them in the offical docs and...
- Regan Heath (3/18) Feb 22 2006 My mistake. They were good words lets put them in the docs.
Why is this illegal? Where does the documentation states this? Does it have something to do with the matter that int[10] is allocated onto the stack? Sometimes I think D losses its abstraction capability when one has to be concerned about this kind of differences. test.d(5): cannot have out or inout parameter of type int[10] (dmd.147 Win) Thanks, Tom;
Feb 21 2006
On Wed, 22 Feb 2006 03:02:22 +0000 (UTC), Tom wrote:Why is this illegal? Where does the documentation states this? Does it have something to do with the matter that int[10] is allocated onto the stack? Sometimes I think D losses its abstraction capability when one has to be concerned about this kind of differences. test.d(5): cannot have out or inout parameter of type int[10]I cannot see why D should be upset with this. The implementation would be just be passing the address of the int[10] array, just as it does for 'in' parameters. In conceptual terms, it is identical to this, which D does allow ... struct X { int[10] x; } void f(inout X q) { q.x[0..$] = 99; } -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 22/02/2006 2:07:00 PM
Feb 21 2006
On Wed, 22 Feb 2006 14:15:32 +1100, Derek Parnell <derek psych.ward> wrote:On Wed, 22 Feb 2006 03:02:22 +0000 (UTC), Tom wrote:Not quite, when you pass something as 'in' you always get a copy of it, this is true even for arrays. The important thing to realise is exactly what it's passing/copying. In this case: int[10] data; void foo(int[10] a) {} foo(data); You're passing a pointer to the array data, 'in' copies that pointer and passes the copy. In this case: int[10] data; void foo(inout int[10] a) {} foo(data); You're not passing a copy of the pointer to the array data, you're passing the actual pointer. As we all know static/fixed arrays have a fixed data pointer which cannot be assigned to or changed in any way. Therefore it's illegal to pass that pointer as 'inout'.Why is this illegal? Where does the documentation states this? Does it have something to do with the matter that int[10] is allocated onto the stack? Sometimes I think D losses its abstraction capability when one has to be concerned about this kind of differences. test.d(5): cannot have out or inout parameter of type int[10]I cannot see why D should be upset with this. The implementation would be just be passing the address of the int[10] array, just as it does for 'in' parameters.In conceptual terms, it is identical to this, which D does allow ... struct X { int[10] x; } void f(inout X q) { q.x[0..$] = 99; }I think it depends on what "conceptual" really means in this case, in terms of "how it works"(TM) I think it's closer to this: const int* data; void foo(inout int* p) {} void bar(int* p) {} void main() { bar(data); foo(data); } which gives: "can only initialize const data inside constructor" for the call to "foo". Note: If you modify p in bar, print the value of data before and after the call and initialise it to the address of an int you'll see that 'p' really is a copy of 'data'. Regan
Feb 21 2006
On Wed, 22 Feb 2006 17:16:30 +1300, Regan Heath wrote:On Wed, 22 Feb 2006 14:15:32 +1100, Derek Parnell <derek psych.ward> wrote:I don't believe that to be entirely accurate. For example, if you pass an 'int' as an 'in' parameter you get a 'mov EAX,<var>' generated, but if you pass the same variable as an 'inout' you get a 'lea EAX,<var>' generated. To me this is saying that whenever an 'inout' parameter is passed, it is the actual address of that parameter passed. Even when the variable is a class instance. In that case an 'in' parameter gets the value of the object reference and an 'inout' gets the address of the object reference. The same with variable-length arrays. However when we get to fixed length arrays, the 'in/inout/out' regime is gets fubar'ed. You can pass a fixed-length array with an 'in' parameter and what get's passed is the address of the first item in the array - which means that the function is free to modify the contents (yes it is an 'in' parameter) but of course the address of the data is not changed (that's what 'in' is really protecting). So in effect, for fixed-length arrays, 'in' and 'inout' are synonymous. Which is not what a normal person would guess. So why not allow 'inout' with fixed-length arrays? Isn't this how a coder would tell the reader that he *intends* to change the passed array's data and 'in' is telling the reader that the coder does NOT intend to change the data.On Wed, 22 Feb 2006 03:02:22 +0000 (UTC), Tom wrote:Not quite, when you pass something as 'in' you always get a copy of it, this is true even for arrays.Why is this illegal? Where does the documentation states this? Does it have something to do with the matter that int[10] is allocated onto the stack? Sometimes I think D losses its abstraction capability when one has to be concerned about this kind of differences. test.d(5): cannot have out or inout parameter of type int[10]I cannot see why D should be upset with this. The implementation would be just be passing the address of the int[10] array, just as it does for 'in' parameters.The important thing to realise is exactly what it's passing/copying. In this case: int[10] data; void foo(int[10] a) {} foo(data); You're passing a pointer to the array data, 'in' copies that pointer and passes the copy.It doesn't actually copy the pointer, it just passes the address of the data ("lea EAX,-8[EBP]").In this case: int[10] data; void foo(inout int[10] a) {} foo(data); You're not passing a copy of the pointer to the array data, you're passing the actual pointer.No, that's what 'in' does.As we all know static/fixed arrays have a fixed data pointer which cannot be assigned to or changed in any way. Therefore it's illegal to pass that pointer as 'inout'.Yes, I can see the logic of this, given that 'in' is designed to protect the reference to the data and not the data itself. To have 'inout' in this context would imply that the coder is trying to change the address of the data and that is obviously not allowed. This fundamental principle of D is not explained well enough in the documentation. 'in' protects that data passed to the function such that any change that the function performs on the passed data, is not passed back to the calling code. For fixed-length arrays the data is the address of first element For variable-length arrays the data is the length of the array and address of the the first element For objects the data is the object reference For structs thee data is the address of the struct contents For intrinsic items the data is the value of the variable.No, I wasn't thinking "implementation" I was thinking "common sense". -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 22/02/2006 3:31:20 PMIn conceptual terms, it is identical to this, which D does allow ... struct X { int[10] x; } void f(inout X q) { q.x[0..$] = 99; }I think it depends on what "conceptual" really means in this case, in terms of "how it works"(TM) I think it's closer to this:
Feb 21 2006
On Wed, 22 Feb 2006 16:09:47 +1100, Derek Parnell <derek psych.ward> wrote:Arrays are passed as references (AKA "array reference"). Passing a static/constant reference as 'inout' should be illegal. Is that not common sense? ReganI think it depends on what "conceptual" really means in this case, in terms of "how it works"(TM) I think it's closer to this:No, I wasn't thinking "implementation" I was thinking "common sense".
Feb 21 2006
On Wed, 22 Feb 2006 16:09:47 +1100, Derek Parnell <derek psych.ward> wrote:On Wed, 22 Feb 2006 17:16:30 +1300, Regan Heath wrote:My knowledge of assembler is practically non existant. Does the 'mov' copy the var into EAX? Does 'lea' copy the address of the var into EAX? Is EAX the parameter to the function? Due to my lack of assembler I can't really back any of my thoughts up with evidence but I'll try and explain what I think is going on...On Wed, 22 Feb 2006 14:15:32 +1100, Derek Parnell <derek psych.ward> wrote:I don't believe that to be entirely accurate. For example, if you pass an 'int' as an 'in' parameter you get a 'mov EAX,<var>' generated, but if you pass the same variable as an 'inout' you get a 'lea EAX,<var>' generated.On Wed, 22 Feb 2006 03:02:22 +0000 (UTC), Tom wrote:Not quite, when you pass something as 'in' you always get a copy of it, this is true even for arrays.Why is this illegal? Where does the documentation states this? Does it have something to do with the matter that int[10] is allocated onto the stack? Sometimes I think D losses its abstraction capability when one has to be concerned about this kind of differences. test.d(5): cannot have out or inout parameter of type int[10]I cannot see why D should be upset with this. The implementation would be just be passing the address of the int[10] array, just as it does for 'in' parameters.To me this is saying that whenever an 'inout' parameter is passed, it is the actual address of that parameter passed. Even when the variable is a class instance.I agree. The key issue is in fact what <var> is in each case. When you pass an int <var> is an int, when you pass a class reference <var> is a class reference, when you pass an array reference <var> is an array reference. So as not to confuse things I'm using the word "variable" to describe 'a' and "parameter" to describe 'b' below. void function(inout int[10] b) {} int[10] a; function(a); What I believe 'inout' does is alias the variable with the parameter. In the case of an array reference <var> is an array reference and the parameter 'b' is therefore simply another name for the same array reference variable 'a'. Modifying the value of 'b' modifies the value of 'a' (and vice-versa. I wonder if I can proove this by using a thread to modify the variable...) The same is true for any inout variable.In that case an 'in' parameter gets the value of the object referenceI agree. In all cases an 'in' parameter gets the value of the <var> which is passed. If <var> is an int you get a new int with the same value, if <var> is a class reference you get a new class reference with the same value, if var is an array reference you get a new array reference with the same value. In all cases 'in' results in a parameter with the same value as the variable. eg. void function(int[10] b) {} int[10] a; function(a); So, 'b' is a brand new array reference with the same value as 'a'. 'b' is a copy of 'a'. The value of a fixed-length array reference is the address of the first item in the array. The value of a variable length array reference is different. It is the address of a struct with a length and data pointer. In other words both array references are pointers (to different things) and their behaviour ends up being the same for both 'in' and 'inout'.and an 'inout' gets the address of the object reference. The same with variable-length arrays. However when we get to fixed length arrays, the 'in/inout/out' regime is gets fubar'ed.I don't agree, my reasoning follows..You can pass a fixed-length array with an 'in' parameter and what get's passed is the address of the first item in the arrayOr rather, a new array reference which has the same value as the original array reference. That value being the memory location of the first item in the array.- which means that the function is free to modify the contents (yes it is an 'in' parameter) but of course the address of the data is not changed (that's what 'in' is really protecting).Correct.So in effect, for fixed-length arrays, 'in' and 'inout' are synonymous.I don't agree. 'inout' aliases the original array reference. 'in' gives you a new array reference with the same value. That is the difference.Which is not what a normal person would guess. So why not allow 'inout' with fixed-length arrays? Isn't this how a coder would tell the reader that he *intends* to change the passed array's data and 'in' is telling the reader that the coder does NOT intend to change the data.WRT array/class references/pointers 'in' promises only 1 thing, that the function will not modify the original array reference. It can promise this because the function always gets a copy of the reference and not the original reference itself. It makes no promise about the content of the array, just like it makes no promise about the content of a class.The "address of the data" is the value of the fixed-length array reference. Copying that value to a new location creates a new array reference, to the same data, a copy of the array reference. In other words, 'in' copies the array reference.The important thing to realise is exactly what it's passing/copying. In this case: int[10] data; void foo(int[10] a) {} foo(data); You're passing a pointer to the array data, 'in' copies that pointer and passes the copy.It doesn't actually copy the pointer, it just passes the address of the data ("lea EAX,-8[EBP]").I think we're disagreeing to the meaning of the terms we're using :) specifically what "passing" means.In this case: int[10] data; void foo(inout int[10] a) {} foo(data); You're not passing a copy of the pointer to the array data, you're passing the actual pointer.No, that's what 'in' does.Agreed.As we all know static/fixed arrays have a fixed data pointer which cannot be assigned to or changed in any way. Therefore it's illegal to pass that pointer as 'inout'.Yes, I can see the logic of this, given that 'in' is designed to protect the reference to the data and not the data itself.To have 'inout' in this context would imply that the coder is trying to change the address of the data and that is obviously not allowed.Agreed.This fundamental principle of D is not explained well enough in the documentation. 'in' protects that data passed to the function such that any change that the function performs on the passed data, is not passed back to the calling code. For fixed-length arrays the data is the address of first element For variable-length arrays the data is the length of the array and address of the the first element For objects the data is the object reference For structs thee data is the address of the struct contents For intrinsic items the data is the value of the variable.I didn't realise this documentation even existed :) I think it does a good job of explaining how it works. I especially like that it tells us what the 2 types of array reference actually are. Regan
Feb 22 2006
On Wed, 22 Feb 2006 23:05:37 +1300, Regan Heath <regan netwin.co.nz> wrote:So as not to confuse things I'm using the word "variable" to describe 'a' and "parameter" to describe 'b' below. void function(inout int[10] b) {} int[10] a; function(a); What I believe 'inout' does is alias the variable with the parameter. In the case of an array reference <var> is an array reference and the parameter 'b' is therefore simply another name for the same array reference variable 'a'. Modifying the value of 'b' modifies the value of 'a' (and vice-versa. I wonder if I can proove this by using a thread to modify the variable...)No threads required to proove aliasing. void foo(inout int a) { printf("addr(a)=0x%08x\n",&a); } void main() { int i; printf("addr(i)=0x%08x\n",&i); foo(i); } Output: addr(i)=0x0012ff34 addr(a)=0x0012ff34 'i' and 'a' are the same int. 'a' is an alias for 'i'. Regan
Feb 22 2006
In article <ops5dcznaa23k2f5 nrage.netwin.co.nz>, Regan Heath says...On Wed, 22 Feb 2006 16:09:47 +1100, Derek Parnell <derek psych.ward> wrote:This isn't true: void f(in int[10] x) { x[0] = 99; } int[10] i; f(i); printf("%d\n", i[0]); // prints '99' So you get a copy of the pointer to the first element. That's plain useless for everyone. I dream 'in' could protect content of the array someday. This is far from abstract a programmer from what's really happening. If I code something like: void f(in int[10] x); Common sense will tell me that the 10 positions of my array are well protected and they shouldn't be touched by 'f' and in return this isn't the behavior. Walter with all respect, this sucks! When will we have real protection attributes? So the 'in' keyword for static arrays are perfectly useless and introduces nothing (while in the background it is really "protecting" the pointer to the first element -that doesn't need any protection-). Regards, Tom;On Wed, 22 Feb 2006 17:16:30 +1300, Regan Heath wrote:On Wed, 22 Feb 2006 14:15:32 +1100, Derek Parnell <derek psych.ward> wrote:On Wed, 22 Feb 2006 03:02:22 +0000 (UTC), Tom wrote:Not quite, when you pass something as 'in' you always get a copy of it, this is true even for arrays.Why is this illegal? Where does the documentation states this? Does it have something to do with the matter that int[10] is allocated onto the stack? Sometimes I think D losses its abstraction capability when one has to be concerned about this kind of differences. test.d(5): cannot have out or inout parameter of type int[10]I cannot see why D should be upset with this. The implementation would be just be passing the address of the int[10] array, just as it does for 'in' parameters.
Feb 22 2006
On Wed, 22 Feb 2006 11:42:15 +0000 (UTC), Tom <Tom_member pathlink.com> wrote:In article <ops5dcznaa23k2f5 nrage.netwin.co.nz>, Regan Heath says...Yes, it is. The key is realising what it is you're actually passing, in this case an array reference. You're not passing the data which is in the array, just the reference to it.On Wed, 22 Feb 2006 16:09:47 +1100, Derek Parnell <derek psych.ward> wrote:This isn't true:On Wed, 22 Feb 2006 17:16:30 +1300, Regan Heath wrote:On Wed, 22 Feb 2006 14:15:32 +1100, Derek Parnell <derek psych.ward> wrote:On Wed, 22 Feb 2006 03:02:22 +0000 (UTC), Tom wrote:Not quite, when you pass something as 'in' you always get a copy of it, this is true even for arrays.Why is this illegal? Where does the documentation states this? Does it have something to do with the matter that int[10] is allocated onto the stack? Sometimes I think D losses its abstraction capability when one has to be concerned about this kind of differences. test.d(5): cannot have out or inout parameter of type int[10]I cannot see why D should be upset with this. The implementation would be just be passing the address of the int[10] array, just as it does for 'in' parameters.void f(in int[10] x) { x[0] = 99; } int[10] i; f(i); printf("%d\n", i[0]); // prints '99' So you get a copy of the pointer to the first element. That's plain useless for everyone. I dream 'in' could protect content of the array someday.See my last reply. The thing you get a copy of is the array reference, not the data to which it refers. The array reference is a pointer which points to the location in memory where the array data is stored, this address is also the location of the first array element, much like: char *p = strdup("this is a test"); the address to which p points is the location of the character 't' from the word 'this'. A fixed-length array is very similar to a plain old pointer, except it also has array bounds checking and a hard coded length available, plus useful array operations. See the docs Derek posted in his last reply, 'in' does not promise to protect the data to which the array reference refers, only the array reference itself.This is far from abstract a programmer from what's really happening. If I code something like: void f(in int[10] x); Common sense will tell me that the 10 positions of my array are well protected and they shouldn't be touched by 'f' and in return this isn't the behavior.I think everyone (including Walter) wants us to be able to do this sort of thing. Whether it's a good idea isn't really in doubt, what is, is how it can be implemented.Walter with all respect, this sucks! When will we have real protection attributes?I suspect we'll have them as soon as Walter devises a way to implement them to his satisfaction.So the 'in' keyword for static arrays are perfectly useless and introduces nothing (while in the background it is really "protecting" the pointer to the first element -that doesn't need any protection-).The 'in' keyword behaves the same way for arrays, classes and any other reference type, it protects the reference itself, not the data to which the reference refers. Regan
Feb 22 2006
In article <ops5dii4gc23k2f5 nrage.netwin.co.nz>, Regan Heath says...On Wed, 22 Feb 2006 11:42:15 +0000 (UTC), Tom <Tom_member pathlink.com> wrote:I know, I thought you meant that 'in' makes a copy of the whole array, not the pointer to it. There's no copy of the array itself.In article <ops5dcznaa23k2f5 nrage.netwin.co.nz>, Regan Heath says...Yes, it is. The key is realising what it is you're actually passing, in this case an array reference. You're not passing the data which is in the array, just the reference to it.On Wed, 22 Feb 2006 16:09:47 +1100, Derek Parnell <derek psych.ward> wrote:This isn't true:On Wed, 22 Feb 2006 17:16:30 +1300, Regan Heath wrote:On Wed, 22 Feb 2006 14:15:32 +1100, Derek Parnell <derek psych.ward> wrote:On Wed, 22 Feb 2006 03:02:22 +0000 (UTC), Tom wrote:Not quite, when you pass something as 'in' you always get a copy of it, this is true even for arrays.Why is this illegal? Where does the documentation states this? Does it have something to do with the matter that int[10] is allocated onto the stack? Sometimes I think D losses its abstraction capability when one has to be concerned about this kind of differences. test.d(5): cannot have out or inout parameter of type int[10]I cannot see why D should be upset with this. The implementation would be just be passing the address of the int[10] array, just as it does for 'in' parameters.Think my post declares clearly that I KNOW THAT.void f(in int[10] x) { x[0] = 99; } int[10] i; f(i); printf("%d\n", i[0]); // prints '99' So you get a copy of the pointer to the first element. That's plain useless for everyone. I dream 'in' could protect content of the array someday.See my last reply. The thing you get a copy of is the array reference, not the data to which it refers.The array reference is a pointer which points to the location in memory where the array data is stored, this address is also the location of the first array element, much like: char *p = strdup("this is a test"); the address to which p points is the location of the character 't' from the word 'this'. A fixed-length array is very similar to a plain old pointer, except it also has array bounds checking and a hard coded length available, plus useful array operations.Agree.See the docs Derek posted in his last reply, 'in' does not promise to protect the data to which the array reference refers, only the array reference itself.Sorry, I didn't understand Derek copied that from docs -in fact I can't find that in the docs [please guide me with a link if you do]-, but rather I think that is his own version of what he think the docs should state (or what has to be added to the docs).I thought I heared that Walter doesn't like the idea of const (that is definitely what in last instance we're talking about), because it can be circumvented with some black magic (or hackish coding). I didn't know he was up to implement that sort of thing (real 'in' parameters). Are you sure?This is far from abstract a programmer from what's really happening. If I code something like: void f(in int[10] x); Common sense will tell me that the 10 positions of my array are well protected and they shouldn't be touched by 'f' and in return this isn't the behavior.I think everyone (including Walter) wants us to be able to do this sort of thing. Whether it's a good idea isn't really in doubt, what is, is how it can be implemented.Hope so.Walter with all respect, this sucks! When will we have real protection attributes?I suspect we'll have them as soon as Walter devises a way to implement them to his satisfaction.Now that you've say it about a 100 times :-D, I ask: When would we have REAL PROTECION ATTRIBUTES FOR REFERENCED DATA RATHER THAN FOR REFERENCES ITSELF (readonly)? Regards, Tom;So the 'in' keyword for static arrays are perfectly useless and introduces nothing (while in the background it is really "protecting" the pointer to the first element -that doesn't need any protection-).The 'in' keyword behaves the same way for arrays, classes and any other reference type, it protects the reference itself, not the data to which the reference refers.
Feb 22 2006
On Thu, 23 Feb 2006 01:30:34 +1100, Tom <Tom_member pathlink.com> wrote: [snip]Yes, they were my own words. You won't find them in the offical docs and that's the point I was trying to make. -- Derek Parnell Melbourne, AustraliaSee the docs Derek posted in his last reply, 'in' does not promise to protect the data to which the array reference refers, only the array reference itself.Sorry, I didn't understand Derek copied that from docs -in fact I can't find that in the docs [please guide me with a link if you do]-, but rather I think that is his own version of what he think the docs should state (or what has to be added to the docs).
Feb 22 2006
On Thu, 23 Feb 2006 02:29:18 +1100, Derek Parnell <derek psych.ward> wrote:On Thu, 23 Feb 2006 01:30:34 +1100, Tom <Tom_member pathlink.com> wrote: [snip]My mistake. They were good words lets put them in the docs. ReganYes, they were my own words. You won't find them in the offical docs and that's the point I was trying to make.See the docs Derek posted in his last reply, 'in' does not promise to protect the data to which the array reference refers, only the array reference itself.Sorry, I didn't understand Derek copied that from docs -in fact I can't find that in the docs [please guide me with a link if you do]-, but rather I think that is his own version of what he think the docs should state (or what has to be added to the docs).
Feb 22 2006