digitalmars.D - pass by reference parameters
- imr1984 (5/5) May 20 2004 ok i asked about this before and i was told that if you pass a large str...
- Achilleas Margaritis (14/19) May 22 2004 struct
- imr1984 (3/24) May 22 2004 yeah i agree with you. Walter would you like to comment on this ? This r...
-
Stewart Gordon
(16/20)
May 24 2004
- imr1984 (7/27) May 24 2004 I think D needs a 'ref' keyword like C# has. This way large structs can ...
- Kris (8/42) May 24 2004 I ran into a similar problem over here: news:c66dlu$1mt7$1@digitaldaemon...
-
Carlos Santander B.
(16/16)
May 24 2004
"imr1984"
escribió en el mensaje - Kris (8/24) May 24 2004 One cannot use 'inout' with a const struct, since by definition it's
- Norbert Nemec (16/46) May 24 2004 Then this boils down to the good old war about "const". Walter decided t...
- Derek Parnell (32/82) May 25 2004 Now I know that D needs to be almost as fast as raw assembler code, so t...
-
Stewart Gordon
(11/20)
May 25 2004
- Regan Heath (28/82) May 25 2004 I think this was a good decision. An object *is* either const or not. Bu...
- Antti =?iso-8859-1?Q?Syk=E4ri?= (20/65) May 27 2004 Hmm, hmm.
- J Anderson (20/33) May 28 2004 in and inout do behave slightly different for objects.
- Billy Zelsnack (4/24) May 24 2004 You can't do this:
- imr1984 (5/21) May 25 2004 inout for a readonly parameter is inaccurate and misleading.
- Norbert Nemec (8/13) May 25 2004 Sounds like a good solution! I really like that! 'in' would be the same
- imr1984 (2/15) May 25 2004 exactly :)
- Andy Friesen (10/15) May 25 2004 You would need to make sure that 'in' references are only passed to
- imr1984 (5/20) May 25 2004 Andy that would also work very well - No I cant think of single reason w...
- Norbert Nemec (8/10) May 25 2004 It is be faster for small structs. But I guess, if you want to go for sp...
- Andy Friesen (5/19) May 25 2004 extern(C/Windows/Pascal) mustn't do this; it defeats their entire reason...
- Norbert Nemec (7/28) May 25 2004 Good question. If the struct is no bigger than one pointer, it is clear ...
- Billy Zelsnack (8/10) May 25 2004 While you are at it. Allow the the extern(C/Windows/Pascal) functions
- Andy Friesen (6/15) May 25 2004 A function using such a struct would be able to create a private copy if...
- Kevin Bealer (27/46) May 26 2004 Depends on reference and pointer semantics. It is faster to copy small ...
- Norbert Nemec (13/15) May 26 2004 I don't hope for too much in that respect. Aliasing is a fundamental pro...
- Derek Parnell (6/14) May 25 2004 There are a couple of Windows API calls that pass a POINT struct by valu...
- Andy Friesen (7/21) May 25 2004 Okay. That more or less solidifies the case for extern C, Pascal, and
- Norbert Nemec (13/28) May 26 2004 True, but every function argument would be readonly by default! Either i...
- Andy Friesen (8/23) May 26 2004 C++ const means const methods, const references, and all the headaches
- Norbert Nemec (21/41) May 26 2004 The problem in C++ is that you can have references/pointers to const. If...
- Arcane Jill (27/49) May 26 2004 Ooh, I can think of squillions of such examples. And at least one exampl...
- Kris (19/69) May 26 2004 +1, AJ
- Derek Parnell (27/35) May 26 2004 Oh is that what all this boils down to? In that case I support the idea ...
- Regan Heath (19/62) May 26 2004 It's going to have to be the latter I think, then it can be checked at
- Derek Parnell (8/79) May 26 2004 Yeah, that makes sense. Also if the caller is worried about a function
- Norbert Nemec (12/47) May 26 2004 Abolishing side-effects completely would be a long step from the C
- Billy Zelsnack (5/10) May 25 2004 haha. That's what I thought 'in' did before I figured out it didn't
ok i asked about this before and i was told that if you pass a large struct parameter by value, the compiler will optomize it to pass by ref if it finds that the function doesnt change the function param. Is this absolutely certain? I often find myself worrying if thats actually the case and just pass a pointer to the struct like i did when using C.
May 20 2004
"imr1984" <imr1984_member pathlink.com> wrote in message news:c8inrv$13jl$1 digitaldaemon.com...ok i asked about this before and i was told that if you pass a largestructparameter by value, the compiler will optomize it to pass by ref if itfindsthat the function doesnt change the function param. Is this absolutelycertain?I often find myself worrying if thats actually the case and just pass apointerto the struct like i did when using C.I think you better pass it with a pointer. I don't think it is possible for a compiler to fully understand how things are used...it may be the case that the struct is implicitely modified in a set of deeply nested functions. I think the variable passing semantics of D are weird: it is a mixture of C (not C++!) and Java: from one hand, we have pointers and structures and the C world, from the other hand, we have Java with references. I wish it as simpler, as in C++: pass by reference, pass by value, independently of the data type.
May 22 2004
yeah i agree with you. Walter would you like to comment on this ? This really needs to be more clearly documented in the spec. In article <c8nldq$slf$1 digitaldaemon.com>, Achilleas Margaritis says..."imr1984" <imr1984_member pathlink.com> wrote in message news:c8inrv$13jl$1 digitaldaemon.com...ok i asked about this before and i was told that if you pass a largestructparameter by value, the compiler will optomize it to pass by ref if itfindsthat the function doesnt change the function param. Is this absolutelycertain?I often find myself worrying if thats actually the case and just pass apointerto the struct like i did when using C.I think you better pass it with a pointer. I don't think it is possible for a compiler to fully understand how things are used...it may be the case that the struct is implicitely modified in a set of deeply nested functions. I think the variable passing semantics of D are weird: it is a mixture of C (not C++!) and Java: from one hand, we have pointers and structures and the C world, from the other hand, we have Java with references. I wish it as simpler, as in C++: pass by reference, pass by value, independently of the data type.
May 22 2004
Achilleas Margaritis wrote: <snip>I think you better pass it with a pointer. I don't think it is possible for a compiler to fully understand how things are used...it may be the case that the struct is implicitely modified in a set of deeply nested functions.<snip> D is supposed to minimise the need for explicit pointer uses. Mabye we could implement copy on write here. Structs passed by reference, but if the function changes the value, it would make a copy of it and use that instead. The only thing is that all modules would need to be compiled with the same convention for it to work. (Hence upgrading/changing your compiler and/or its options would necessitate a clean and rebuild.) And when you get into libs, it opens a whole new can of worms.... Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
May 24 2004
passed by reference without nasty pointers. The way i see it, this is the only way to support this because as Stewart says if you have a function exported from a library, and it takes a struct, the only way for the compiler to know that the exported func takes the struct by Ref is if its indicated in the prototype with the ref keyword. In article <c8sgn9$1ocs$1 digitaldaemon.com>, Stewart Gordon says...Achilleas Margaritis wrote: <snip>I think you better pass it with a pointer. I don't think it is possible for a compiler to fully understand how things are used...it may be the case that the struct is implicitely modified in a set of deeply nested functions.<snip> D is supposed to minimise the need for explicit pointer uses. Mabye we could implement copy on write here. Structs passed by reference, but if the function changes the value, it would make a copy of it and use that instead. The only thing is that all modules would need to be compiled with the same convention for it to work. (Hence upgrading/changing your compiler and/or its options would necessitate a clean and rebuild.) And when you get into libs, it opens a whole new can of worms.... Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
May 24 2004
I ran into a similar problem over here: news:c66dlu$1mt7$1 digitaldaemon.com - Kris "imr1984" <imr1984_member pathlink.com> wrote in message news:c8tbvq$fm$1 digitaldaemon.com...passed by reference without nasty pointers. The way i see it, this is theonlyway to support this because as Stewart says if you have a functionexported froma library, and it takes a struct, the only way for the compiler to knowthat theexported func takes the struct by Ref is if its indicated in the prototypewiththe ref keyword. In article <c8sgn9$1ocs$1 digitaldaemon.com>, Stewart Gordon says...Achilleas Margaritis wrote: <snip>I think you better pass it with a pointer. I don't think it is possible for a compiler to fully understand how things are used...it may be the case that the struct is implicitely modified in a set of deeply nested functions.<snip> D is supposed to minimise the need for explicit pointer uses. Mabye we could implement copy on write here. Structs passed by reference, but if the function changes the value, it would make a copy of it and use that instead. The only thing is that all modules would need to be compiled with the same convention for it to work. (Hence upgrading/changing your compiler and/or its options would necessitate a clean and rebuild.) And when you get into libs, it opens a whole new can of worms.... Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
May 24 2004
"imr1984" <imr1984_member pathlink.com> escribió en el mensaje news:c8tbvq$fm$1 digitaldaemon.com | passed by reference without nasty pointers. The way i see it, this is the only | way to support this because as Stewart says if you have a function exported from | a library, and it takes a struct, the only way for the compiler to know that the | exported func takes the struct by Ref is if its indicated in the prototype with | the ref keyword. | What's wrong with inout? ----------------------- Carlos Santander Bernal
May 24 2004
One cannot use 'inout' with a const struct, since by definition it's read-only. - Kris "Carlos Santander B." <carlos8294 msn.com> wrote in message news:c8udnv$205u$1 digitaldaemon.com..."imr1984" <imr1984_member pathlink.com> escribió en el mensaje news:c8tbvq$fm$1 digitaldaemon.combe| passed by reference without nasty pointers. The way i see it, this istheonly | way to support this because as Stewart says if you have a function exported from | a library, and it takes a struct, the only way for the compiler to know that the | exported func takes the struct by Ref is if its indicated in theprototypewith | the ref keyword. | What's wrong with inout? ----------------------- Carlos Santander Bernal
May 24 2004
Then this boils down to the good old war about "const". Walter decided to make "const" a storage class, not a type modifier. This means, we have const objects, you can take a pointer from them, but then the compiler does not help you in tracking that they were const. Introducing "ref" in addition to "inout" would just hide this fact in a very obscure way. "inout mytype arg" would be "mytype &arg" in C++, while "ref mytype arg" would be "const mytype &arg". I believe that whole business of "in", "out" and "inout" arguments is flawed. My first expectation, when I saw these was, that that they are "copy-in/copy-out" arguments. The specs are not very precise when they talk about this question. Somehow, I have the feeling, that D tries to hide the complexity of reference/value arguments from the user, but, at the same time, obscures and cripples the concept completely. My opinion: neither the C++ nor the D way are the solution. I don't know the solution, but it has to be out there somewhere. Kris wrote:One cannot use 'inout' with a const struct, since by definition it's read-only. - Kris "Carlos Santander B." <carlos8294 msn.com> wrote in message news:c8udnv$205u$1 digitaldaemon.com..."imr1984" <imr1984_member pathlink.com> escribió en el mensaje news:c8tbvq$fm$1 digitaldaemon.combe| passed by reference without nasty pointers. The way i see it, this istheonly | way to support this because as Stewart says if you have a function exported from | a library, and it takes a struct, the only way for the compiler to know that the | exported func takes the struct by Ref is if its indicated in theprototypewith | the ref keyword. | What's wrong with inout? ----------------------- Carlos Santander Bernal
May 24 2004
On Tue, 25 May 2004 08:44:21 +0200, Norbert Nemec wrote:Then this boils down to the good old war about "const". Walter decided to make "const" a storage class, not a type modifier. This means, we have const objects, you can take a pointer from them, but then the compiler does not help you in tracking that they were const. Introducing "ref" in addition to "inout" would just hide this fact in a very obscure way. "inout mytype arg" would be "mytype &arg" in C++, while "ref mytype arg" would be "const mytype &arg". I believe that whole business of "in", "out" and "inout" arguments is flawed. My first expectation, when I saw these was, that that they are "copy-in/copy-out" arguments. The specs are not very precise when they talk about this question. Somehow, I have the feeling, that D tries to hide the complexity of reference/value arguments from the user, but, at the same time, obscures and cripples the concept completely. My opinion: neither the C++ nor the D way are the solution. I don't know the solution, but it has to be out there somewhere.See below ...Kris wrote:Now I know that D needs to be almost as fast as raw assembler code, so the method I'm about to describe will not be useful in all cases for D, but it is another way of thinking about parameter passing... In another language that I use a great deal, all parameters are passed by value (semantically). In this language, there are only two effective data types - numbers and vectors. As vectors can be arbitarily large, they are actually passed by reference but on the first write to a vector parameter, the language automatically does a copy of it and changes the reference to point to the copy. It's actually a bit more sophisticated than that, but the net effect from the coder's point of view is that you can never alter a variable being passed as a parameter from within the function being called. Also, the automatic copy-on-write feature makes this 'pass by value' fairly efficient. BTW it also does automatic garbage collection for you too. For example (not quality code but just an example!): function ToUpper(sequence x) for i = 1 to length(x) do if x[i] >= 'a' and x[i] <= 'z' then x[i] = x[i] + ('A' - 'a') end if end for return x end function sequence A, B A = "abc" B = ToUpper(A) After the call to ToUpper(), 'A' will still be "abc" and 'B' will be "ABC". In fact, if you needed to update 'A' you would code 'A = ToUpper(A)'. -- Derek 25/May/04 5:18:36 PMOne cannot use 'inout' with a const struct, since by definition it's read-only. - Kris "Carlos Santander B." <carlos8294 msn.com> wrote in message news:c8udnv$205u$1 digitaldaemon.com..."imr1984" <imr1984_member pathlink.com> escribió en el mensaje news:c8tbvq$fm$1 digitaldaemon.combe| passed by reference without nasty pointers. The way i see it, this istheonly | way to support this because as Stewart says if you have a function exported from | a library, and it takes a struct, the only way for the compiler to know that the | exported func takes the struct by Ref is if its indicated in theprototypewith | the ref keyword. | What's wrong with inout? ----------------------- Carlos Santander Bernal
May 25 2004
Norbert Nemec wrote: <snip>I believe that whole business of "in", "out" and "inout" arguments is flawed. My first expectation, when I saw these was, that that they are "copy-in/copy-out" arguments. The specs are not very precise when they talk about this question. Somehow, I have the feeling, that D tries to hide the complexity of reference/value arguments from the user, but, at the same time, obscures and cripples the concept completely. My opinion: neither the C++ nor the D way are the solution. I don't know the solution, but it has to be out there somewhere.<snip top of upside-down reply> Maybe in should've meant pass by reference, making it like out/inout, leaving no modifier to mean pass by value. At least as far as structs and atomic types go, don't ask me about arrays, obects and the like.... Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
May 25 2004
On Tue, 25 May 2004 08:44:21 +0200, Norbert Nemec <Norbert.Nemec gmx.de> wrote:Then this boils down to the good old war about "const". Walter decided to make "const" a storage class, not a type modifier.I think this was a good decision. An object *is* either const or not. But lets not re-start this argument.This means, we have const objects, you can take a pointer from them, but then the compiler does not help you in tracking that they were const.This should be fixed. Can you point a 'pointer to non-const' (does D even have 'pointer to const') at a const object? if so, perhaps this shouldn't be allowed.Introducing "ref" in addition to "inout" would just hide this fact in a very obscure way. "inout mytype arg" would be "mytype &arg" in C++, while "ref mytype arg" would be "const mytype &arg".I don't like the 'ref' idea, I think in, out and inout can do what we need.I believe that whole business of "in", "out" and "inout" arguments is flawed. My first expectation, when I saw these was, that that they are "copy-in/copy-out" arguments. The specs are not very precise when they talk about this question. Somehow, I have the feeling, that D tries to hide the complexity of reference/value arguments from the user, but, at the same time, obscures and cripples the concept completely. My opinion: neither the C++ nor the D way are the solution. I don't know the solution, but it has to be out there somewhere.If we adopt this idea of passing by reference *all* the time, you'd have something like: in - pass by reference, any attempt to modify causes a compile time error. out - pass by reference, initialized on entry. inout - pass by reference. a const object passed as an inout or out parameter would cause a compile time error. (I realise it may not be simple to detect the above compile time errors) I don't think you need to copy-in/copy-out. If the function writer wants to modify an 'in' parameter, then it's either not an 'in' parameter, or they only want to do it for the duration of the function so... int fn(in int _a) { int a = _a; } will suffice to make a copy they can modify for the duration of the function. What am I missing? Regan.Kris wrote:-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/One cannot use 'inout' with a const struct, since by definition it's read-only. - Kris "Carlos Santander B." <carlos8294 msn.com> wrote in message news:c8udnv$205u$1 digitaldaemon.com..."imr1984" <imr1984_member pathlink.com> escribió en el mensaje news:c8tbvq$fm$1 digitaldaemon.com canbe| passed by reference without nasty pointers. The way i see it, this istheonly | way to support this because as Stewart says if you have a function exported from | a library, and it takes a struct, the only way for the compiler to know that the | exported func takes the struct by Ref is if its indicated in theprototypewith | the ref keyword. | What's wrong with inout? ----------------------- Carlos Santander Bernal
May 25 2004
In article <c8upj2$2m2j$1 digitaldaemon.com>, Norbert Nemec wrote:I believe that whole business of "in", "out" and "inout" arguments is flawed. My first expectation, when I saw these was, that that they are "copy-in/copy-out" arguments. The specs are not very precise when they talkHmm, hmm. I just got a strange revelation... since D doesn't have const, doesn't that actually mean that inout and in are practically the same thing? (If we're talking about classes that is. Yes, it means precisely that. "in" arguments can be clobbered ruthlessly.) Actually I could think differently: since const can never be anything else than documentation of the programmer's intent, it isn't actually needed. "in" and "inout" could be as well replaced with C++'s const reference and inout with reference. Except that an "in" parameter doesn't protect the programmer from accidents. It's precisely like a const T& parameter of C++, which is then const_cast<T&>:ed implicitly inside the function body. I didn't even think (or test) about the value arguments (ints, structs and the like) yet, maybe the in/inout stuff is just cleaner when you take them into account. -Anttiabout this question. Somehow, I have the feeling, that D tries to hide the complexity of reference/value arguments from the user, but, at the same time, obscures and cripples the concept completely. My opinion: neither the C++ nor the D way are the solution. I don't know the solution, but it has to be out there somewhere. Kris wrote:-- I will not be using Plan 9 in the creation of weapons of mass destruction to be used by nations other than the US.One cannot use 'inout' with a const struct, since by definition it's read-only. - Kris "Carlos Santander B." <carlos8294 msn.com> wrote in message news:c8udnv$205u$1 digitaldaemon.com..."imr1984" <imr1984_member pathlink.com> escribió en el mensaje news:c8tbvq$fm$1 digitaldaemon.combe| passed by reference without nasty pointers. The way i see it, this istheonly | way to support this because as Stewart says if you have a function exported from | a library, and it takes a struct, the only way for the compiler to know that the | exported func takes the struct by Ref is if its indicated in theprototypewith | the ref keyword. | What's wrong with inout? ----------------------- Carlos Santander Bernal
May 27 2004
Antti Sykäri wrote:In article <c8upj2$2m2j$1 digitaldaemon.com>, Norbert Nemec wrote:in and inout do behave slightly different for objects. void test(A a) { a = new A; } void test2(inout A a) { a = new A; } void main() { A a = new A; test(a); //what is a test2(a); //what is a } -- -Anderson: http://badmama.com.au/~anderson/I believe that whole business of "in", "out" and "inout" arguments is flawed. My first expectation, when I saw these was, that that they are "copy-in/copy-out" arguments. The specs are not very precise when they talkHmm, hmm. I just got a strange revelation... since D doesn't have const, doesn't that actually mean that inout and in are practically the same thing? (If we're talking about classes that is. Yes, it means precisely that. "in" arguments can be clobbered ruthlessly.)
May 28 2004
You can't do this: float3 vecA=float3(0,0,0); float3 vecB=add(vecA,float3(0,0,1)); Carlos Santander B. wrote:"imr1984" <imr1984_member pathlink.com> escribió en el mensaje news:c8tbvq$fm$1 digitaldaemon.com | passed by reference without nasty pointers. The way i see it, this is the only | way to support this because as Stewart says if you have a function exported from | a library, and it takes a struct, the only way for the compiler to know that the | exported func takes the struct by Ref is if its indicated in the prototype with | the ref keyword. | What's wrong with inout? ----------------------- Carlos Santander Bernal
May 24 2004
inout for a readonly parameter is inaccurate and misleading. Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect. In article <c8udnv$205u$1 digitaldaemon.com>, Carlos Santander B. says..."imr1984" <imr1984_member pathlink.com> escribió en el mensaje news:c8tbvq$fm$1 digitaldaemon.com | passed by reference without nasty pointers. The way i see it, this is the only | way to support this because as Stewart says if you have a function exported from | a library, and it takes a struct, the only way for the compiler to know that the | exported func takes the struct by Ref is if its indicated in the prototype with | the ref keyword. | What's wrong with inout? ----------------------- Carlos Santander Bernal
May 25 2004
imr1984 wrote:inout for a readonly parameter is inaccurate and misleading. Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.Sounds like a good solution! I really like that! 'in' would be the same thing as 'const &' in C++. No semantic difference to the current situation (except in the case where another function changes the data behind the reference while the called function is running but that is dangerous in any case). Just a clean way to tell the compiler what the calling convention for a given function should be (Which is an information that the compiler cannot easily deduct automatically).
May 25 2004
In article <c8vhji$tkh$1 digitaldaemon.com>, Norbert Nemec says...imr1984 wrote:exactly :)inout for a readonly parameter is inaccurate and misleading. Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.Sounds like a good solution! I really like that! 'in' would be the same thing as 'const &' in C++. No semantic difference to the current situation (except in the case where another function changes the data behind the reference while the called function is running but that is dangerous in any case). Just a clean way to tell the compiler what the calling convention for a given function should be (Which is an information that the compiler cannot easily deduct automatically).
May 25 2004
imr1984 wrote:inout for a readonly parameter is inaccurate and misleading. Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.You would need to make sure that 'in' references are only passed to methods as 'in' arguments, and so on and so forth. It's C++ const all over again. What might be better is if the ABI said that all structs are always passed by reference. In the case of 'in' parameters, the compiler would be responsible for creating a temporary copy if one is needed. (ie if it thinks the struct is written to) Are there any arguments for passing structs by value? -- andy
May 25 2004
In article <c8vnlv$17f4$1 digitaldaemon.com>, Andy Friesen says...imr1984 wrote:Andy that would also work very well - No I cant think of single reason why you would want to pass a struct by value. I wish the spec was more clear on what actually happens under the hood with regards to parameter passing. So I guess that kinda makes the 'in' keyword redundant?inout for a readonly parameter is inaccurate and misleading. Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.You would need to make sure that 'in' references are only passed to methods as 'in' arguments, and so on and so forth. It's C++ const all over again. What might be better is if the ABI said that all structs are always passed by reference. In the case of 'in' parameters, the compiler would be responsible for creating a temporary copy if one is needed. (ie if it thinks the struct is written to) Are there any arguments for passing structs by value? -- andy
May 25 2004
Andy Friesen wrote:imr1984 wrote: Are there any arguments for passing structs by value?It is be faster for small structs. But I guess, if you want to go for speed, you would use inlining anyway, in which case it does not really matter. It just has to be clear what the semantics are, no matter what the compiler does to achive it. Furthermore, it has to be clear how other languages are interfaced. If you want to interface a C function that takes a struct as value on the stack, you have to be able to specify that interface in D.
May 25 2004
Norbert Nemec wrote:Andy Friesen wrote:Why is it faster? And how small is small?imr1984 wrote: Are there any arguments for passing structs by value?It is be faster for small structs. But I guess, if you want to go for speed, you would use inlining anyway, in which case it does not really matter. It just has to be clear what the semantics are, no matter what the compiler does to achive it.Furthermore, it has to be clear how other languages are interfaced. If you want to interface a C function that takes a struct as value on the stack, you have to be able to specify that interface in D.extern(C/Windows/Pascal) mustn't do this; it defeats their entire reason to exist. I'm suggesting behaviour for extern(D) only. -- andy
May 25 2004
Andy Friesen wrote:Norbert Nemec wrote:Good question. If the struct is no bigger than one pointer, it is clear that it is faster since you simply save one step of dereferencing. If it is slightly bigger, dereferencing may still be more expensive than copying. Hard to tll.Andy Friesen wrote:Why is it faster? And how small is small?imr1984 wrote: Are there any arguments for passing structs by value?It is be faster for small structs. But I guess, if you want to go for speed, you would use inlining anyway, in which case it does not really matter. It just has to be clear what the semantics are, no matter what the compiler does to achive it.Maybe extern(C/Windows/Pascal/...) should not use the in/inout/out modifiers at all but offer a completely separate set of modifiers fit for each case?Furthermore, it has to be clear how other languages are interfaced. If you want to interface a C function that takes a struct as value on the stack, you have to be able to specify that interface in D.extern(C/Windows/Pascal) mustn't do this; it defeats their entire reason to exist. I'm suggesting behaviour for extern(D) only.
May 25 2004
Maybe extern(C/Windows/Pascal/...) should not use the in/inout/out modifiers at all but offer a completely separate set of modifiers fit for each case?While you are at it. Allow the the extern(C/Windows/Pascal) functions have 'const' in the prototype. I end up having to do this a lot: extern(C) { void lookyLooky(/*const*/ Something* something); } In one of the C libraries I use I could just grab all of the functions intact without any changes if I didn't have to comment out all the 'const'.
May 25 2004
Norbert Nemec wrote:Andy Friesen wrote:A function using such a struct would be able to create a private copy if it was determined that doing so would be faster, right?Why is it faster? And how small is small?Good question. If the struct is no bigger than one pointer, it is clear that it is faster since you simply save one step of dereferencing. If it is slightly bigger, dereferencing may still be more expensive than copying. Hard to tll.Maybe extern(C/Windows/Pascal/...) should not use the in/inout/out modifiers at all but offer a completely separate set of modifiers fit for each case?Everything except 'in' should be illegal, I think. Those conventions are already well established standards; D shouldn't mess with them. -- andy
May 25 2004
In article <c8vrut$1e87$1 digitaldaemon.com>, Andy Friesen says...Norbert Nemec wrote:Depends on reference and pointer semantics. It is faster to copy small structs, because you can cache all or parts of them in registers. Consider this common swap idiom: struct foo { int a; int b; } // foo x : passed into function if (x.a > x.b) { int c = x.a; x.a = x.b; x.b = c; } If structs are pass-by-value, this needs to load x.a and x.b, write x.b to x.a, write x.a to x.b. I assume enough optimization that c can be eliminated. Thus there are four memory operations if the loop is true, two if not. If pass by reference, and "aliasing" assumptions are C89 style, then there are at least 6 memory operations, because the structs may have changed between statements. This is (one reason) why some C and C++ code will pass a struct by pointer, then copy pieces into local variables. Local variables can be "registerized" but structs can only be registerized if the current thread can be assumed to be the only user of the struct. Hopefully, D will use semantics that default to higher optimization and less aliasing, (In contradiction of a previous suggestion of mine ;). KevinAndy Friesen wrote:Why is it faster? And how small is small?imr1984 wrote: Are there any arguments for passing structs by value?It is be faster for small structs. But I guess, if you want to go for speed, you would use inlining anyway, in which case it does not really matter. It just has to be clear what the semantics are, no matter what the compiler does to achive it.Furthermore, it has to be clear how other languages are interfaced. If you want to interface a C function that takes a struct as value on the stack, you have to be able to specify that interface in D.extern(C/Windows/Pascal) mustn't do this; it defeats their entire reason to exist. I'm suggesting behaviour for extern(D) only. -- andy
May 26 2004
Kevin Bealer wrote:Hopefully, D will use semantics that default to higher optimization and less aliasing, (In contradiction of a previous suggestion of mine ;).I don't hope for too much in that respect. Aliasing is a fundamental problem in a language as soon as you have references. In Fortran77, it was trivial to avoid aliasing by simply stating that function arguments may not be aliased. This is, because function arguments were the only source of aliased symbols. Outside of a function, two different symbols always stand for two different objects in memory. Only in functions call, new names for symbols are introduced, so it is easy to prohibit this and have the problem solved completely. In languages that have pointers, aliasing happens everywhere. Prohibiting aliased function arguments only captures the tip of the iceberg. A function might use pointers from all kinds of sources, nested data-structures or whatever.
May 26 2004
On Tue, 25 May 2004 08:14:17 -0700, Andy Friesen wrote: [snip]What might be better is if the ABI said that all structs are always passed by reference. In the case of 'in' parameters, the compiler would be responsible for creating a temporary copy if one is needed. (ie if it thinks the struct is written to) Are there any arguments for passing structs by value?There are a couple of Windows API calls that pass a POINT struct by value. -- Derek 26/May/04 9:40:42 AM
May 25 2004
Derek Parnell wrote:On Tue, 25 May 2004 08:14:17 -0700, Andy Friesen wrote: [snip]Okay. That more or less solidifies the case for extern C, Pascal, and Windows all behaving exactly as they do now. Should extern (D) preserve this behaviour for consistency's sake, or is this an opportunity for D to do the Right Thing even in the face of naive code? (indeed, make the naive approach the best one) -- andyWhat might be better is if the ABI said that all structs are always passed by reference. In the case of 'in' parameters, the compiler would be responsible for creating a temporary copy if one is needed. (ie if it thinks the struct is written to) Are there any arguments for passing structs by value?There are a couple of Windows API calls that pass a POINT struct by value.
May 25 2004
Andy Friesen wrote:imr1984 wrote:True, but every function argument would be readonly by default! Either it has no argument modifier, meaning call-by-value, or it is 'in', meaning call by read-only-reference.inout for a readonly parameter is inaccurate and misleading. Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.You would need to make sure that 'in' references are only passed to methods as 'in' arguments, and so on and so forth.It's C++ const all over again.No! The problem in C++ was, that "const" had to be explicitly specified. So if you forgot to say it in some function, you had problems using that function legitimately. In D, you will have to explicitly state 'inout', if you want to have a read-write reference.What might be better is if the ABI said that all structs are always passed by reference. In the case of 'in' parameters, the compiler would be responsible for creating a temporary copy if one is needed. (ie if it thinks the struct is written to)Why not prohibit writing to function arguments alltogether (unless they are inout/out)? It is that strange C feature to make every argument automatically a local variable. I always found it bad style to use this. If you need a local variable, why not just declare one?
May 26 2004
Norbert Nemec wrote:The problem in C++ was, that "const" had to be explicitly specified. So if you forgot to say it in some function, you had problems using that function legitimately. In D, you will have to explicitly state 'inout', if you want to have a read-write reference.C++ const means const methods, const references, and all the headaches that they entail. The theory seems sound enough, but the compiler can't use const to optimize anything and I can't recall any instances offhand where const saved the day. I can, however, recall a whole lot of compiler errors caused by forgetting to const this or that.Most languages I have used allow this. Why not? -- andyWhat might be better is if the ABI said that all structs are always passed by reference. In the case of 'in' parameters, the compiler would be responsible for creating a temporary copy if one is needed. (ie if it thinks the struct is written to)Why not prohibit writing to function arguments alltogether (unless they are inout/out)? It is that strange C feature to make every argument automatically a local variable. I always found it bad style to use this. If you need a local variable, why not just declare one?
May 26 2004
Andy Friesen wrote:Norbert Nemec wrote:The problem in C++ is that you can have references/pointers to const. If you disallow taking the address of a const variable, the problem of const references disappears. Objects can never be const, since they are always handled as reference and you cannot have literal objects. This solves the demand for const methods. Leaves us only with const for call-by-reference arguments: this could be solved by making arguments read-only generally. If "in" would declare an argument as call-by-reference argument, this would mean you can only use it in places where a const would be allowed as well. If you use a literal as "in" argument, the compiler will have to place it in the constant data segment to be able to create a reference to it, but there is no chance anyone might ever try to write to that memory.The problem in C++ was, that "const" had to be explicitly specified. So if you forgot to say it in some function, you had problems using that function legitimately. In D, you will have to explicitly state 'inout', if you want to have a read-write reference.C++ const means const methods, const references, and all the headaches that they entail. The theory seems sound enough, but the compiler can't use const to optimize anything and I can't recall any instances offhand where const saved the day. I can, however, recall a whole lot of compiler errors caused by forgetting to const this or that.Because it collides with call-by-reference. For "inout/out", there is no problem, since assigning to the referenced data actually means changing that data outside of the function. For "in" parameters, on the other hand, the compiler will have to make a copy of that data, which, in a way, defies the purpose of call-by-reference. Most old programming languages allow it, since it may save one copy-operation. Today, with optimizing compilers, this does not really matter any more, so I can only call it bad programming style.Why not prohibit writing to function arguments alltogether (unless they are inout/out)? It is that strange C feature to make every argument automatically a local variable. I always found it bad style to use this. If you need a local variable, why not just declare one?Most languages I have used allow this. Why not?
May 26 2004
In article <c91jku$11uv$1 digitaldaemon.com>, Andy Friesen says...C++ const means const methods, const references, and all the headaches that they entail. The theory seems sound enough, but the compiler can't use const to optimize anything and I can't recall any instances offhand where const saved the day.Ooh, I can think of squillions of such examples. And at least one example when one of my time "worked around" my const declaration with a pointer trick, and held the project up for about two weeks while the whole team attempted to figure out how and why the heap was getting corrupted! Our app was multithreaded - that's when these things really matter.I can, however, recall a whole lot of compiler errors caused by forgetting to const this or that.That's what happens when you call functions written by other people who DIDN'T use const. I've always thought that C++ would be a much better language if it everything was const by default, and you needed a keyword, nonconst, say, to specify otherwise. That way, if you wrote a function like:char * strcpy(char * dst, char * src);it would fail to compile until you changed it to:char * strcpy(nonconst char * dst, char * src);(although the error would refer to the line that attempted to modify *dst, not the declaration). As things stand, forgetting const is not a compile error. Instead, it becomes impossible to use const unless you go the whole hog and change every single function you call to use the C++ const convention. In the case of D, I would dearly love to be able to declare a function like:void myFunction( in MyObject myObject )****and have the compiler flag an error**** if the referenced object is modified. I cannot stress how greatly this would assist in bug catching. Right now the only way to do anything even remotely similar to this is:void myFunction( in MyObject myObject ) in { myObject_backup = new MyObject(myObject); } out { assert(myObject == myObject_backup); } body { debug MyObject myObject_backup; }Sheesh! After all, putting const (or in, or nonconst, or whatever) into a function declaration is simply that - a contract which the function must fulfil. If it fails to fulfil that contract, it's a bug. With all of D's emphasis on contracts, it baffles me why D doesn't implement this most useful one. Arcane Jill
May 26 2004
+1, AJ Though it might seem draconian to some, defaulting arguments to read-only access would indeed avoid a ream of oft hard-to-find bugs. Would likely offer up some optimization opportunities also - Kris. "Arcane Jill" <Arcane_member pathlink.com> wrote in message news:c920je$1jqr$1 digitaldaemon.com...In article <c91jku$11uv$1 digitaldaemon.com>, Andy Friesen says...whenC++ const means const methods, const references, and all the headaches that they entail. The theory seems sound enough, but the compiler can't use const to optimize anything and I can't recall any instances offhand where const saved the day.Ooh, I can think of squillions of such examples. And at least one exampleone of my time "worked around" my const declaration with a pointer trick,andheld the project up for about two weeks while the whole team attempted tofigureout how and why the heap was getting corrupted! Our app wasmultithreaded -that's when these things really matter.DIDN'TI can, however, recall a whole lot of compiler errors caused by forgetting to const this or that.That's what happens when you call functions written by other people whouse const. I've always thought that C++ would be a much better language if iteverythingwas const by default, and you needed a keyword, nonconst, say, to specify otherwise. That way, if you wrote a function like:notchar * strcpy(char * dst, char * src);it would fail to compile until you changed it to:char * strcpy(nonconst char * dst, char * src);(although the error would refer to the line that attempted to modify *dst,the declaration). As things stand, forgetting const is not a compileerror.Instead, it becomes impossible to use const unless you go the whole hogandchange every single function you call to use the C++ const convention. In the case of D, I would dearly love to be able to declare a functionlike:itvoid myFunction( in MyObject myObject )****and have the compiler flag an error**** if the referenced object is modified. I cannot stress how greatly this would assist in bug catching. Right now the only way to do anything even remotely similar to this is:void myFunction( in MyObject myObject ) in { myObject_backup = new MyObject(myObject); } out { assert(myObject == myObject_backup); } body { debug MyObject myObject_backup; }Sheesh! After all, putting const (or in, or nonconst, or whatever) into a function declaration is simply that - a contract which the function must fulfil. Iffails to fulfil that contract, it's a bug. With all of D's emphasis on contracts, it baffles me why D doesn'timplementthis most useful one. Arcane Jill
May 26 2004
On Wed, 26 May 2004 08:02:24 -0700, Kris wrote:+1, AJ Though it might seem draconian to some, defaulting arguments to read-only access would indeed avoid a ream of oft hard-to-find bugs. Would likely offer up some optimization opportunities also - Kris.Oh is that what all this boils down to? In that case I support the idea as well. Having worked with a language where it is impossible to change the value of function arguments, I at first thought this was a draconian 'feature'. But over the years now, I've come around to believing it has saved me from *so many* bugs AND it makes programming easier knowing that the arguments you pass to some function are never altered by that function. No side-effects! Wonderful! All parameters are only modified through explict assignments by the CALLING code and not the CALLED code. If D is not going to do automatic copy-on-write (and I don't think it should), then having the default of read-only arguments AND being allowed to explictly nominate which arguments can be modified by a function, seems to be a good idea. One question that remains is at what point do we nominate the modifiable arguments - the caller or the called? In other words ... If the caller does it (my preference so far)... A = FuncA( inout B, C, D) If the called does it ... int FuncA( inout int X, int Y, int Z) { . . . } I suppose it is not a compiler or a runtime error if the function attempts to modify read-only arguments because it could be said that its just using them as local variables. But maybe this needs more discussion and thought. -- Derek 27/May/04 10:17:35 AM
May 26 2004
On Thu, 27 May 2004 10:30:39 +1000, Derek Parnell <derek psych.ward> wrote:On Wed, 26 May 2004 08:02:24 -0700, Kris wrote:It's going to have to be the latter I think, then it can be checked at compile time (in some/most/all? cases) Also the function writer knows what access the function needs to it's parameters, not the caller.+1, AJ Though it might seem draconian to some, defaulting arguments to read-only access would indeed avoid a ream of oft hard-to-find bugs. Would likely offer up some optimization opportunities also - Kris.Oh is that what all this boils down to? In that case I support the idea as well. Having worked with a language where it is impossible to change the value of function arguments, I at first thought this was a draconian 'feature'. But over the years now, I've come around to believing it has saved me from *so many* bugs AND it makes programming easier knowing that the arguments you pass to some function are never altered by that function. No side-effects! Wonderful! All parameters are only modified through explict assignments by the CALLING code and not the CALLED code. If D is not going to do automatic copy-on-write (and I don't think it should), then having the default of read-only arguments AND being allowed to explictly nominate which arguments can be modified by a function, seems to be a good idea. One question that remains is at what point do we nominate the modifiable arguments - the caller or the called? In other words ... If the caller does it (my preference so far)... A = FuncA( inout B, C, D) If the called does it ... int FuncA( inout int X, int Y, int Z) { . . . }I suppose it is not a compiler or a runtime error if the function attempts to modify read-only arguments because it could be said that its just using them as local variables. But maybe this needs more discussion and thought.I think it should be an error. If you want to modify them, then either: - they're incorrectly labelled read-only - you only want to modify them for the scope of the function, in which case what is wrong with: struct foo { int a; } int foobar(in foo a) { foo b = a; //modify/use b; } Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
May 26 2004
On Thu, 27 May 2004 12:59:10 +1200, Regan Heath wrote:On Thu, 27 May 2004 10:30:39 +1000, Derek Parnell <derek psych.ward> wrote:Yeah, that makes sense. Also if the caller is worried about a function changing the parameters, the caller can pass a copy. int Xcopy = X; foobar( Xcopy ); -- Derek 27/May/04 11:58:28 AMOn Wed, 26 May 2004 08:02:24 -0700, Kris wrote:It's going to have to be the latter I think, then it can be checked at compile time (in some/most/all? cases) Also the function writer knows what access the function needs to it's parameters, not the caller.+1, AJ Though it might seem draconian to some, defaulting arguments to read-only access would indeed avoid a ream of oft hard-to-find bugs. Would likely offer up some optimization opportunities also - Kris.Oh is that what all this boils down to? In that case I support the idea as well. Having worked with a language where it is impossible to change the value of function arguments, I at first thought this was a draconian 'feature'. But over the years now, I've come around to believing it has saved me from *so many* bugs AND it makes programming easier knowing that the arguments you pass to some function are never altered by that function. No side-effects! Wonderful! All parameters are only modified through explict assignments by the CALLING code and not the CALLED code. If D is not going to do automatic copy-on-write (and I don't think it should), then having the default of read-only arguments AND being allowed to explictly nominate which arguments can be modified by a function, seems to be a good idea. One question that remains is at what point do we nominate the modifiable arguments - the caller or the called? In other words ... If the caller does it (my preference so far)... A = FuncA( inout B, C, D) If the called does it ... int FuncA( inout int X, int Y, int Z) { . . . }I suppose it is not a compiler or a runtime error if the function attempts to modify read-only arguments because it could be said that its just using them as local variables. But maybe this needs more discussion and thought.I think it should be an error. If you want to modify them, then either: - they're incorrectly labelled read-only - you only want to modify them for the scope of the function, in which case what is wrong with: struct foo { int a; } int foobar(in foo a) { foo b = a; //modify/use b; }
May 26 2004
Derek Parnell wrote:On Wed, 26 May 2004 08:02:24 -0700, Kris wrote:Abolishing side-effects completely would be a long step from the C philosophy and a rather radical change in D. I don't think, we can get all that far. Of course, other languages (especially functional languages) do it and it saves them a number of problems. But C/C++/D are not functional. All I thought about was making 'in' parameters readonly within the function, instead of turning them into local variables that can be changed, but whose value is lost. Alternatively, you could have the compiler to automatically insert a copying instruction on read-only call-by-reference arguments.+1, AJ Though it might seem draconian to some, defaulting arguments to read-only access would indeed avoid a ream of oft hard-to-find bugs. Would likely offer up some optimization opportunities also - Kris.Oh is that what all this boils down to? In that case I support the idea as well. Having worked with a language where it is impossible to change the value of function arguments, I at first thought this was a draconian 'feature'. But over the years now, I've come around to believing it has saved me from *so many* bugs AND it makes programming easier knowing that the arguments you pass to some function are never altered by that function. No side-effects! Wonderful! All parameters are only modified through explict assignments by the CALLING code and not the CALLED code.If D is not going to do automatic copy-on-write (and I don't think it should), then having the default of read-only arguments AND being allowed to explictly nominate which arguments can be modified by a function, seems to be a good idea. One question that remains is at what point do we nominate the modifiable arguments - the caller or the called? In other words ... If the caller does it (my preference so far)... A = FuncA( inout B, C, D) If the called does it ... int FuncA( inout int X, int Y, int Z) { . . . }The second one if needed in any case (and is in the specs already) since 'inout' is a matter of the interface. Adding the first one would only be redundancy which is not exactly D style.
May 26 2004
imr1984 wrote:inout for a readonly parameter is inaccurate and misleading. Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.haha. That's what I thought 'in' did before I figured out it didn't really mean anything. It makes sense though. 'out' means out only. 'inout' means both. 'in' would make sense to mean in only.
May 25 2004