www.digitalmars.com         C & C++   DMDScript  

D - "inout" is wrong name

reply "Sandor Hojtsy" <hojtsy index.hu> writes:
Consider passing a value as "inout" parameter to a function.
Then both the caller and the called functions continue to use the same
value, by multithreading.
Now when will the changes of the inout parameter be incorporated into the
original variable?
Immediately, or when the called function returns?
The specification does not tell. (Walter: please put it in)
The "inout" name suggests the later, but the first happens (i hope).
Therefore the name "inout" is not really intuitive. I would rather suggest
"ref", because what is happening is passing a parameter by reference.

Sandor
Oct 03 2002
next sibling parent reply "Walter" <walter digitalmars.com> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into the
 original variable?
 Immediately, or when the called function returns?
When the called function sets it to a value. I'm not sure why it matters.
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather suggest
 "ref", because what is happening is passing a parameter by reference.
True, but I like the consistency with "in" and "out" parameters.
Oct 03 2002
next sibling parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"Walter" <walter digitalmars.com> wrote in message
news:anh2vv$9jb$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
 Immediately, or when the called function returns?
When the called function sets it to a value. I'm not sure why it matters.
int global_var; void fn(inout int a, inout int b) { a = 3; printf("a = %d\n", a); printf("b = %d\n", b); printf("global_var = %d\n", global_var); } int main() { global_var = 2; fn(global_var, global_var); return 0; } A "real" inout parameter passing would print: a = 3 b = 2 global_var = 2 So it is not "inout" but "ref"
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by reference.
True, but I like the consistency with "in" and "out" parameters.
The name is consistant, but the behaviour is not.
Oct 07 2002
parent reply Evan McClanahan <evan dontSPAMaltarinteractive.com> writes:
Sandor Hojtsy wrote:
 "Walter" <walter digitalmars.com> wrote in message
 news:anh2vv$9jb$1 digitaldaemon.com...
 
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...

Consider passing a value as "inout" parameter to a function.
Then both the caller and the called functions continue to use the same
value, by multithreading.
Now when will the changes of the inout parameter be incorporated into
the
original variable?
Immediately, or when the called function returns?
When the called function sets it to a value. I'm not sure why it matters.
int global_var; void fn(inout int a, inout int b) { a = 3; printf("a = %d\n", a); printf("b = %d\n", b); printf("global_var = %d\n", global_var); } int main() { global_var = 2; fn(global_var, global_var); return 0; } A "real" inout parameter passing would print: a = 3 b = 2 global_var = 2
I don't think that I know what you mean. Semantically, inout should be something that expects a value in, but can still change it in the function. So I would expect inout to do what I imagine that it does: a = 3 b = 3 global_var = 3
 So it is not "inout" but "ref"
This is something of a pathological case, perhaps even an error, since both inouts end up pointing to the same place. Yeah, inout might be a ref, but I imagine that it would be extremely hard for the compiler to do compile time checking that the inout parameters are all different for each function. In fact, I can't really see a case where it would be proper or useful to do this, nor a way to pass it back in a reasonable manner in any case. I think that the keyword is clear enough, and that if possible what you're doing in the above code should be classed as an error, or at least proscribed in the documentation. Evan
Oct 07 2002
next sibling parent "Sandor Hojtsy" <hojtsy index.hu> writes:
"Evan McClanahan" <evan dontSPAMaltarinteractive.com> wrote in message
news:anrqs3$ic5$1 digitaldaemon.com...
 Sandor Hojtsy wrote:
 "Walter" <walter digitalmars.com> wrote in message
 news:anh2vv$9jb$1 digitaldaemon.com...

"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...

Consider passing a value as "inout" parameter to a function.
Then both the caller and the called functions continue to use the same
value, by multithreading.
Now when will the changes of the inout parameter be incorporated into
the
original variable?
Immediately, or when the called function returns?
When the called function sets it to a value. I'm not sure why it
matters.
 int global_var;

 void fn(inout int a, inout int b)
 {
   a = 3;
   printf("a = %d\n", a);
   printf("b = %d\n", b);
   printf("global_var = %d\n", global_var);
 }

 int main()
 {
   global_var = 2;
   fn(global_var, global_var);
   return 0;
 }

 A "real" inout parameter passing would print:
 a = 3
 b = 2
 global_var = 2
I don't think that I know what you mean. Semantically, inout should be something that expects a value in, but can still change it in the function. So I would expect inout to do what I imagine that it does: a = 3 b = 3 global_var = 3
 So it is not "inout" but "ref"
This is something of a pathological case, perhaps even an error, since both inouts end up pointing to the same place.
Both parameters and the global_var too.
  Yeah, inout might be a
 ref, but I imagine that it would be extremely hard for the compiler to
 do compile time checking that the inout parameters are all different for
 each function.
I am not requesting a compile time check to enforce copy/copyback semantics. I propose to rename the keyword to "ref" to indicate that there is no copy/copyback semantics.
 In fact, I can't really see a case where it would be
 proper or useful to do this, nor a way to pass it back in a reasonable
 manner in any case.  I think that the keyword is clear enough, and that
 if possible what you're doing in the above code should be classed as an
 error,
Which violates the rule of ... ??
 or at least proscribed in the documentation.

 Evan
Oct 08 2002
prev sibling parent reply edgein123 aol.com writes:
In article <anrqs3$ic5$1 digitaldaemon.com>, Evan McClanahan says...
..
 void fn(inout int a, inout int b)
 {
   a = 3;
   printf("a = %d\n", a);
   printf("b = %d\n", b);
   printf("global_var = %d\n", global_var);
 }
 
 int main()
 {
   global_var = 2;
   fn(global_var, global_var);
   return 0;
 }
 
 A "real" inout parameter passing would print:
 a = 3
 b = 2
 global_var = 2
Actually, for pass-by-copy, the value of global_var is ambiguous. The value of either 2 or 3 is possible depending on whether we look at parameters from left-to-right or right-to-left.
I don't think that I know what you mean.  Semantically, inout should be 
something that expects a value in, but can still change it in the 
function.  So I would expect inout to do what I imagine that it does:
a = 3
b = 3
global_var = 3

 So it is not "inout" but "ref"
This is something of a pathological case, perhaps even an error, since both inouts end up pointing to the same place. Yeah, inout might be a ref, but I imagine that it would be extremely hard for the compiler to do compile time checking that the inout parameters are all different for each function. In fact, I can't really see a case where it would be proper or useful to do this, nor a way to pass it back in a reasonable manner in any case. I think that the keyword is clear enough, and that if possible what you're doing in the above code should be classed as an error, or at least proscribed in the documentation. Evan
Let me just recap what the three alternatives are, their strengths and weakness, and then my suggested approach to solving this problem. inout: This indicates that a parameter is used for both input and output. The problem seems to be the calling mechanism used. For instance, are we using pass-by-reference, pass-by-value-result (pass-by-copy), or pass-by-name. ref: This indicates that the parameter is passed-by-reference (a pointer). The problem is that this method does not indicate that the parameter is used for input, output, or both. shared: This particular name really does not tell you anything, other than the fact the variable can be modified by the called routine. This is perhaps the worst option because it leaves two things unanswered: (1) are we using pass-by-reference or pass-by-value-result; and, (2) is the parameter used for input, output, or both. For those that don't know the difference between these calling methods, here is a quick definition of each, assuming the parameter we are passing is called ARG. pass-by-value: The contents ARG are passed to the function. pass-by-reference: The address of ARG is passed to the function, allowing modification by the called function. pass-by-value-result: A temporary, T, is assigned the value of ARG. Next, we call the function using pass-by-reference using T in place of ARG. Lastly, when the function returns ARG is assigned the final value of T. pass-by-name: This one is best explained by an example (in pseudo-C): int index; int array[2] = {2, 2}; void sub(int param /*assuming pass-by-name*/) { param = 3; index++; param = 5; } void main() { index = 0; sub(aray[index]); // array is now {3, 5} } The reason for this is because the body of sub gets transformed into: array[index] = 3; index++; array[index] = 5; Having said all of that, I believe the following rules present a much more elegant solution to all of these problems: 1) All parameters shall be passed via either pass-by-value or pass-by-reference. 2) All parameters deemed as input shall be read-only. 3) The parameter passing mechanism used for input parameters shall be determined by the compiler. 4) All output parameters shall be passed in using pass-by-reference. 5) Output parameters that are referenced prior to writing to them shall result in an error message. 6) All inout parameters shall be passed in pass-by-reference. 7) All inout parameteres shall be initialized prior to the call of said function. (Note, that this would be easy to verifiy for a local variable but can be extremely hard if not impossible for globals). 8) All parameters shall be assumed to be an input parameter unless explicitly stated otherwise. In some of the examples, people want to pass in a large array without doing the copy, and as such labeled them as inout. Note that this is no longer necessary due to rules (2) and (3). Other problems such as those presented in function 'fn' are covered by rules (1) and (6). - Eric
Feb 11 2004
parent Scott Wood <scott buserror.net> writes:
On Thu, 12 Feb 2004 03:19:52 +0000 (UTC), edgein123 aol.com <edgein123 aol.com>
wrote:
 inout: This indicates that a parameter is used for both input and
 output. The problem seems to be the calling mechanism used. For
 instance, are we using pass-by-reference, pass-by-value-result
 (pass-by-copy), or pass-by-name.
If you disallow aliases, then it doesn't matter which is used in terms of correctness. This allows future ABIs to use pass-by-value, which could be more efficient (especially on ABIs that pass parameters in registers). Disallowing aliases allows other important optimizations as well, especially concerning arrays. -Scott
Feb 12 2004
prev sibling parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"Walter" <walter digitalmars.com> wrote in message
news:anh2vv$9jb$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
 Immediately, or when the called function returns?
When the called function sets it to a value. I'm not sure why it matters.
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by reference.
True, but I like the consistency with "in" and "out" parameters.
Lets consider you are passing a 1000 byte structure to a function. You don't wan't to change it, but you don't wan't to make a copy of it either, because that is slow. Passing by pointer is complex, and unnecessary. You specify "inout" to enable pass by reference. But conceptually this is not an "inout" parameter 'cause it is never changed. It is a constant reference, as in C++. You still have to use the keyword "inout" ruining the whole concept of *self documentation*. struct large { int f[1000]; } void fn(inout large a, int i) { printf("%d", a.f[i]); // "a" is never changed } Sandor
Oct 09 2002
parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:ao0mr5$124s$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:anh2vv$9jb$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
 Immediately, or when the called function returns?
When the called function sets it to a value. I'm not sure why it
matters.
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by reference.
True, but I like the consistency with "in" and "out" parameters.
Lets consider you are passing a 1000 byte structure to a function. You
don't
 wan't to change it, but you don't wan't to make a copy of it either,
because
 that is slow. Passing by pointer is complex, and unnecessary. You specify
 "inout" to enable pass by reference. But conceptually this is not an
"inout"
 parameter 'cause it is never changed. It is a constant reference, as in
C++.
 You still have to use the keyword "inout" ruining the whole concept of
*self
 documentation*.
I agree, but you mean reference to a constant, a constant reference would be a reference that can not be changed to refer toanything else (like a C++ reference, some languages allow references to be "re-referenced") I find it odd that D does not support "read only" parameters as many compilers use this to perform optimisations such as register cacheing of structure values in non leaf functions in callee save registers.
 struct large {
   int f[1000];
 }

 void fn(inout large a, int i)
 {
   printf("%d", a.f[i]);  // "a" is never changed
 }

 Sandor
Oct 09 2002
parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
news:ao10nf$1cqf$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:ao0mr5$124s$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:anh2vv$9jb$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the
same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated
into
 the
 original variable?
 Immediately, or when the called function returns?
When the called function sets it to a value. I'm not sure why it
matters.
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by
reference.
 True, but I like the consistency with "in" and "out" parameters.
Lets consider you are passing a 1000 byte structure to a function. You
don't
 wan't to change it, but you don't wan't to make a copy of it either,
because
 that is slow. Passing by pointer is complex, and unnecessary. You
specify
 "inout" to enable pass by reference. But conceptually this is not an
"inout"
 parameter 'cause it is never changed. It is a constant reference, as in
C++.
 You still have to use the keyword "inout" ruining the whole concept of
*self
 documentation*.
I agree, but you mean reference to a constant,
Hmm. It was C++ terminology. A reference to a constant would mean creating a reference to an otherwise constant object.
 a constant reference would be a reference that can not be changed to refer
 toanything else (like a C++ reference, some languages allow references to
be
 "re-referenced")
In D some references can be rereferenced (references to Object), and some references cannot be rereferenced: (inout parameters). If you pass an Object as inout, it is a two level reference, of which only the second level can be rereferenced.
 I find it odd that D does not support "read only" parameters as many
 compilers use this to perform optimisations
 such as register cacheing of structure values in non leaf functions in
 callee save registers.
IMHO, for most programmers, "read only" parameters and objects are not performace issues, but they increase the expressive power, and foolproofness of the language. And yes, I think they would be usefull in D. I can recall Walter telling he don't like them, but I don't remember why. But the thing I wanted to point out in the first place, was not "create read only parameters", but that the "inout" keyword is not properly named.
 struct large {
   int f[1000];
 }

 void fn(inout large a, int i)
 {
   printf("%d", a.f[i]);  // "a" is never changed
 }

 Sandor
Oct 09 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:ao34k0$fqs$1 digitaldaemon.com...
 IMHO, for most programmers, "read only" parameters and objects are not
 performace issues, but they increase the expressive power, and
foolproofness
 of the language. And yes, I think they would be usefull in D. I can recall
 Walter telling he don't like them, but I don't remember why.
The C++ notion of a const reference parameter: 1) adds a lot of clutter to function prototypes 2) is useless for optimization, since you can still change it 3) adds a lot of complexity to the overload rules and typing system 4) in my experience, it has never found a bug for me In other words, it's benefit/cost ratio is too small.
Oct 18 2002
next sibling parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
"Walter" <walter digitalmars.com> wrote in message
news:aooksv$1ftm$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:ao34k0$fqs$1 digitaldaemon.com...
 IMHO, for most programmers, "read only" parameters and objects are not
 performace issues, but they increase the expressive power, and
foolproofness
 of the language. And yes, I think they would be usefull in D. I can
recall
 Walter telling he don't like them, but I don't remember why.
 The C++ notion of a const reference parameter:

 1) adds a lot of clutter to function prototypes
 2) is useless for optimization, since you can still change it
it is a common complaint about gcc -O3 which assumes when you say const you mean const and are not going to cast within your function and abuse the item.
 3) adds a lot of complexity to the overload rules and typing system
and does not go far enought, for simple pointers to simple items, its fine, const item * i; I can't change item item * const i; I can change item but not the pointer. const item * const i; I can't change either but if 'item' contained a pointer to another item, then I can change what that points to. currently been writing some graphical device code, and what to be able to make sure that images (struct with a pointer to the image data) are not written to, unless they are 'offscreen' images rather than ROM'ed images.
 4) in my experience, it has never found a bug for me
I have found it very useful, i.e. void myFunc( Item * dest, const Item * src ); stop you trying to write to ROM locations when doing embedded dev. but that's about it.
 In other words, it's benefit/cost ratio is too small.
agree, BUT how would 'D' be ROM-able on resource limited platforms without being able to put static data into read only memory ? in C static int stuff[] = { .... } // allocated RAM space puts copy in ROM static const int stuff[] = { .... } // allocated ROM only. I personally feel that immutablility is more often a runtime property of an item rather than a compile time property and IF D every has immutable items, then the contracts need to allow the programmer to define the range and depth of the effect. Rather than const,final like types, I think meta-classes that allow the programmer to define the way an Object can be used, so your parameter are declared as meta-class types not the Object type (the meta class would have revered inheritance rules, because it starts from the unrestricted and becomes more restrictive, and obviously a less restricted meta is passable as a more restrictive meta) so you could define the object public interface contract with a syntax like ( public/private are part of the objects access control list and are not relevent here, this just defines which if any of the objects members are immuatble and how far reaching the effect) meta MyObj : MyObjImpl { const field1; // field1, and any child fields or items referenced by this field are immutable via this interface final field2; // field2 is immutable BUT items referenced by this field are mutable } meta MyObjImmutable : MyObj { const field2; // final fields in sub-meta-class can be make MORE restricted but never less default final; // all non mentioned fields are immutable } int readObj( MyObjImmutable readme ) { ... } void writePartObj( MyObj canmodifyme_partly ) { int i; i = readObj( canmodifyme_partly ); // allowed : meta-classes have reverse polymorpic rules. ..... } MyObjImpl imp = new MyObjImpl(); writePartObj( imp ); // allowed meta classes have reverse polymorphic semantics the compiler could either perform compile time only checks or runtime checks too (in which case a meta is a pointer to obj + ptr to meta-info). if you allow casts then you need the runtime checks too with templating and sensible use, I do not see a need to allow casts on meta-classes. Mike.
Oct 18 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
news:aop2g5$1taf$1 digitaldaemon.com...
 The C++ notion of a const reference parameter:
 1) adds a lot of clutter to function prototypes
 2) is useless for optimization, since you can still change it
it is a common complaint about gcc -O3 which assumes when you say const
you
 mean const and are not going to cast within your function and abuse the
 item.
There's another problem with const precluding optimizations - suppose one object is pointed to by both a regular and a const pointer (perfectly legal C++). The former changes the latter behind its back, so to speak.
 how would 'D' be ROM-able on resource limited platforms without being able
 to put static data into read only memory ?
 in C
 static int stuff[] = { .... } // allocated RAM space puts copy in ROM
 static const int stuff[] = { .... } // allocated ROM only.
That will work in D because const is a storage class.
 I personally feel that immutablility is more often a runtime property of
an
 item rather than a compile time property and IF D every has immutable
items,
 then the contracts need to allow the programmer to define the range and
 depth of the effect.

 Rather than const,final like types, I think meta-classes that allow the
 programmer to define the way an Object can be used, so your parameter are
 declared as meta-class types not the Object type
 (the meta class would have revered inheritance rules, because it starts
from
 the unrestricted and becomes more restrictive, and obviously a less
 restricted meta is passable as a more restrictive meta)

 so you could define the object public interface contract with a syntax
like
 ( public/private are part of the objects access control list and are not
 relevent here, this just defines which if any of the objects members are
 immuatble and how far reaching the effect)
 meta MyObj : MyObjImpl
 {
     const field1;   // field1, and any child fields or items referenced by
 this field are immutable via this interface
     final field2; // field2 is immutable BUT items referenced by this
field
 are mutable
 }

 meta MyObjImmutable : MyObj
 {
     const field2;    // final fields in sub-meta-class can be make MORE
 restricted but never less
     default final;    // all non mentioned fields are immutable
 }

 int readObj( MyObjImmutable readme ) { ... }
 void writePartObj( MyObj canmodifyme_partly ) {
     int i;
     i = readObj( canmodifyme_partly ); // allowed : meta-classes have
 reverse polymorpic rules.
 .....
 }

 MyObjImpl imp = new MyObjImpl();
 writePartObj( imp ); // allowed meta classes have reverse polymorphic
 semantics

 the compiler could either perform compile time only checks or runtime
checks
 too
 (in which case a meta is a pointer to obj + ptr to meta-info).
 if you allow casts then you need the runtime checks too
 with templating and sensible use, I do not see a need to allow casts on
 meta-classes.

 Mike.
Oct 20 2002
next sibling parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
If you have this situation you should use volatile on things you want
changes to show up immediately on.  Then the change will take effect on all
copies immediately, but everything else can use the old values.

If you think something might change, don't keep a const reference to it.

Just because something might break isn't a good enough reason not to do the
optimization.  Just needs enough language warnings and good support for
volatile too.

In many cases you use const when you don't expect something to change and/or
don't care if it changes.

Sean

"Walter" <walter digitalmars.com> wrote in message
news:ap08fe$75h$1 digitaldaemon.com...
 "Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
 news:aop2g5$1taf$1 digitaldaemon.com...
 The C++ notion of a const reference parameter:
 1) adds a lot of clutter to function prototypes
 2) is useless for optimization, since you can still change it
it is a common complaint about gcc -O3 which assumes when you say const
you
 mean const and are not going to cast within your function and abuse the
 item.
There's another problem with const precluding optimizations - suppose one object is pointed to by both a regular and a const pointer (perfectly
legal
 C++). The former changes the latter behind its back, so to speak.

 how would 'D' be ROM-able on resource limited platforms without being
able
 to put static data into read only memory ?
 in C
 static int stuff[] = { .... } // allocated RAM space puts copy in ROM
 static const int stuff[] = { .... } // allocated ROM only.
That will work in D because const is a storage class.
 I personally feel that immutablility is more often a runtime property of
an
 item rather than a compile time property and IF D every has immutable
items,
 then the contracts need to allow the programmer to define the range and
 depth of the effect.

 Rather than const,final like types, I think meta-classes that allow the
 programmer to define the way an Object can be used, so your parameter
are
 declared as meta-class types not the Object type
 (the meta class would have revered inheritance rules, because it starts
from
 the unrestricted and becomes more restrictive, and obviously a less
 restricted meta is passable as a more restrictive meta)

 so you could define the object public interface contract with a syntax
like
 ( public/private are part of the objects access control list and are not
 relevent here, this just defines which if any of the objects members are
 immuatble and how far reaching the effect)
 meta MyObj : MyObjImpl
 {
     const field1;   // field1, and any child fields or items referenced
by
 this field are immutable via this interface
     final field2; // field2 is immutable BUT items referenced by this
field
 are mutable
 }

 meta MyObjImmutable : MyObj
 {
     const field2;    // final fields in sub-meta-class can be make MORE
 restricted but never less
     default final;    // all non mentioned fields are immutable
 }

 int readObj( MyObjImmutable readme ) { ... }
 void writePartObj( MyObj canmodifyme_partly ) {
     int i;
     i = readObj( canmodifyme_partly ); // allowed : meta-classes have
 reverse polymorpic rules.
 .....
 }

 MyObjImpl imp = new MyObjImpl();
 writePartObj( imp ); // allowed meta classes have reverse polymorphic
 semantics

 the compiler could either perform compile time only checks or runtime
checks
 too
 (in which case a meta is a pointer to obj + ptr to meta-info).
 if you allow casts then you need the runtime checks too
 with templating and sensible use, I do not see a need to allow casts on
 meta-classes.

 Mike.
Oct 21 2002
next sibling parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
news:ap0mop$oka$1 digitaldaemon.com...
 If you have this situation you should use volatile on things you want
 changes to show up immediately on.  Then the change will take effect on
all
 copies immediately, but everything else can use the old values.
What do you mean by "all copies"? Copies do not change.
 If you think something might change, don't keep a const reference to it.
You do. Const reference means you (this module/function/object) are not authorized to change it. But it doesn't mean it can never be changed by anyone. So if a value can be changed I should give permission to everybody to change it?
 Just because something might break isn't a good enough reason not to do
the
 optimization.  Just needs enough language warnings and good support for
 volatile too.
I don't want to see a compiler warning me about having an object with both const and non-const references. I do that deliberately, as part of good design, using a valid language feature.
 In many cases you use const when you don't expect something to change
and/or
 don't care if it changes.
Can you show an example when you "use const when you don't care if it changes", please?
 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:ap08fe$75h$1 digitaldaemon.com...
 "Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
 news:aop2g5$1taf$1 digitaldaemon.com...
 The C++ notion of a const reference parameter:
 1) adds a lot of clutter to function prototypes
 2) is useless for optimization, since you can still change it
it is a common complaint about gcc -O3 which assumes when you say
const
 you
 mean const and are not going to cast within your function and abuse
the
 item.
There's another problem with const precluding optimizations - suppose
one
 object is pointed to by both a regular and a const pointer (perfectly
legal
 C++). The former changes the latter behind its back, so to speak.

 how would 'D' be ROM-able on resource limited platforms without being
able
 to put static data into read only memory ?
 in C
 static int stuff[] = { .... } // allocated RAM space puts copy in ROM
 static const int stuff[] = { .... } // allocated ROM only.
That will work in D because const is a storage class.
 I personally feel that immutablility is more often a runtime property
of
 an
 item rather than a compile time property and IF D every has immutable
items,
 then the contracts need to allow the programmer to define the range
and
 depth of the effect.

 Rather than const,final like types, I think meta-classes that allow
the
 programmer to define the way an Object can be used, so your parameter
are
 declared as meta-class types not the Object type
 (the meta class would have revered inheritance rules, because it
starts
 from
 the unrestricted and becomes more restrictive, and obviously a less
 restricted meta is passable as a more restrictive meta)

 so you could define the object public interface contract with a syntax
like
 ( public/private are part of the objects access control list and are
not
 relevent here, this just defines which if any of the objects members
are
 immuatble and how far reaching the effect)
 meta MyObj : MyObjImpl
 {
     const field1;   // field1, and any child fields or items
referenced
 by
 this field are immutable via this interface
     final field2; // field2 is immutable BUT items referenced by this
field
 are mutable
 }

 meta MyObjImmutable : MyObj
 {
     const field2;    // final fields in sub-meta-class can be make
MORE
 restricted but never less
     default final;    // all non mentioned fields are immutable
 }

 int readObj( MyObjImmutable readme ) { ... }
 void writePartObj( MyObj canmodifyme_partly ) {
     int i;
     i = readObj( canmodifyme_partly ); // allowed : meta-classes have
 reverse polymorpic rules.
 .....
 }

 MyObjImpl imp = new MyObjImpl();
 writePartObj( imp ); // allowed meta classes have reverse polymorphic
 semantics

 the compiler could either perform compile time only checks or runtime
checks
 too
 (in which case a meta is a pointer to obj + ptr to meta-info).
 if you allow casts then you need the runtime checks too
 with templating and sensible use, I do not see a need to allow casts
on
 meta-classes.

 Mike.
Oct 21 2002
parent "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:ap2q48$30o2$1 digitaldaemon.com...
 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:ap0mop$oka$1 digitaldaemon.com...
 If you have this situation you should use volatile on things you want
 changes to show up immediately on.  Then the change will take effect on
all
 copies immediately, but everything else can use the old values.
What do you mean by "all copies"? Copies do not change.
I meant all volatile const items. Oh well I probably made Walter hurl with this suggestion.
 If you think something might change, don't keep a const reference to it.
You do. Const reference means you (this module/function/object) are not authorized to change it. But it doesn't mean it can never be changed by anyone. So if a value can be changed I should give permission to everybody to change it?
 Just because something might break isn't a good enough reason not to do
the
 optimization.  Just needs enough language warnings and good support for
 volatile too.
I don't want to see a compiler warning me about having an object with both const and non-const references. I do that deliberately, as part of good design, using a valid language feature.
Right.
 In many cases you use const when you don't expect something to change
and/or
 don't care if it changes.
Can you show an example when you "use const when you don't care if it changes", please?
struct workstruct { int a,b,c; }; void dowork(const workstruct& mat, workstruct& result) { // here I likely don't give a crap if some thread is busy updating mat.a while I'm working result.a += mat.a; result.b += mat.a; result.c += mat.a; } If I did care, I'd use volatile like so: void dothreadsafework(const volatile workstruct& mat, workstruct& result) { // this will "work" even if some thread is updating mat. If that's what you want. result.a += mat.a; result.b += mat.a; result.c += mat.a; } Of course when you leave the function and come back, sure you'll probably want to refresh the view of the struct. class worker { const workstruct& mat; worker(const workstruct& amat) : mat(amat) {} void dowork(workstruct& result) { result.a += mat.a; result.b += mat.a; result.c += mat.a; } } The compiler has to make a few assumptions in order to generate good code (at very least cache things in registers). I'm willing to give up a lot of knowledge about what's going on in other threads in order to get that speed. That's what volatile is for... for those times when you need the absolute latest values all the time. 95% of the time, you don't. And I don't want my compiler dumping registers to the stack and reloading registers if it doesn't absolutely have to. Sean
Oct 22 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
news:ap0mop$oka$1 digitaldaemon.com...
 If you have this situation you should use volatile on things you want
 changes to show up immediately on.  Then the change will take effect on
all
 copies immediately, but everything else can use the old values.
 If you think something might change, don't keep a const reference to it.
 Just because something might break isn't a good enough reason not to do
the
 optimization.  Just needs enough language warnings and good support for
 volatile too.
 In many cases you use const when you don't expect something to change
and/or
 don't care if it changes.
Unfortunately, I can't implement compiler optimizations that assume const means const, because it doesn't and too many programs break. This is one of the reasons why const is useless as a type modifier.
Oct 24 2002
parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
Isn't this a good opportunity to fix the language so that it supports these
kinds of optimizations, rather than hinder them?

Surely something can be done.

What things would you need to be true in order to cache locals in registers
across function calls?  Make an attribute that supports the functionality,
and make the compiler enforce it.  You don't have to use it, but if you do,
you know the compiler will be able to generate better code.  Maybe "const"
isn't the right choice of words, maybe "cachelocalaccess" would be better.

I still think that readonly is a desirable attribute even if it doesn't buy
you any optimization potential.  It seems like if you don't have it, you
leave dangerous holes in a component's armor that can be abused without so
much as a typecast or compiler warning.  Or abused completely by accident.

Sean

"Walter" <walter digitalmars.com> wrote in message
news:ap9jaq$l0m$1 digitaldaemon.com...
 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:ap0mop$oka$1 digitaldaemon.com...
 If you have this situation you should use volatile on things you want
 changes to show up immediately on.  Then the change will take effect on
all
 copies immediately, but everything else can use the old values.
 If you think something might change, don't keep a const reference to it.
 Just because something might break isn't a good enough reason not to do
the
 optimization.  Just needs enough language warnings and good support for
 volatile too.
 In many cases you use const when you don't expect something to change
and/or
 don't care if it changes.
Unfortunately, I can't implement compiler optimizations that assume const means const, because it doesn't and too many programs break. This is one
of
 the reasons why const is useless as a type modifier.
Oct 24 2002
parent "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
news:apad69$1hgm$1 digitaldaemon.com...
 Isn't this a good opportunity to fix the language so that it supports
these
 kinds of optimizations, rather than hinder them?

 Surely something can be done.

 What things would you need to be true in order to cache locals in
registers
 across function calls?  Make an attribute that supports the functionality,
 and make the compiler enforce it.  You don't have to use it, but if you
do,
 you know the compiler will be able to generate better code.  Maybe "const"
 isn't the right choice of words, maybe "cachelocalaccess" would be better.

 I still think that readonly is a desirable attribute even if it doesn't
buy
 you any optimization potential.  It seems like if you don't have it, you
 leave dangerous holes in a component's armor that can be abused without so
 much as a typecast or compiler warning.  Or abused completely by accident.
Perhaps in a future version, but for now I think things are pretty full. Gotta do foreach, lambda functions, etc. <g>
Oct 28 2002
prev sibling parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
 There's another problem with const precluding optimizations - suppose one
 object is pointed to by both a regular and a const pointer (perfectly
legal
 C++). The former changes the latter behind its back, so to speak.
as pointed out the const should have been a const volatile, you can't change it but someone else can. I would still like to be able to mark a parameter as immutable, which I guess in C would be const volatile in that it does not say that the object/item can not be altered by another thread or h/w, but that I can not modify it. to gain the optimisability, you could add a "theadsafe" modifier, I agree the default behaviour should err on the side of caution (all class methods virtual etc) but it should be possible to get back the performance in most cases. as an aside, have you though about changing the build from a 2 stage compile, link into a 3 stage build so it is compile,gather,link, where the gather stage, pulls in all the objects, and then with a full view of the final codebase can convert some calls to non-virtual and perform optimisations on immutable items etc, in a similar fashion to Java/CLR dynamic compilers.
 how would 'D' be ROM-able on resource limited platforms without being
able
 to put static data into read only memory ?
 in C
 static int stuff[] = { .... } // allocated RAM space puts copy in ROM
 static const int stuff[] = { .... } // allocated ROM only.
That will work in D because const is a storage class.
My mistake, and I agree const is constant for all time.
Oct 21 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
news:ap0uki$119j$1 digitaldaemon.com...
 as an aside, have you though about changing the build from a 2 stage
 compile, link into a 3 stage build
 so it is compile,gather,link, where the gather stage, pulls in all the
 objects, and then with a full view of the final codebase can convert  some
 calls to non-virtual and perform optimisations on immutable items etc, in
a
 similar fashion to Java/CLR dynamic compilers.
Too many void*'s in C++ usually put an end to these kinds of global optimizations. I tried to do something similar once with function register usage across separate compilation items, it just worked out that so many things defeat the optimization that there wasn't a payoff.
Oct 24 2002
parent Matthias Becker <Matthias_member pathlink.com> writes:
Too many void*'s in C++ usually put an end to these kinds of global
optimizations. I tried to do something similar once with function register
usage across separate compilation items, it just worked out that so many
things defeat the optimization that there wasn't a payoff.
Are there too many void *s in D?
Feb 12 2004
prev sibling parent Matthias Becker <Matthias_member pathlink.com> writes:
2) is useless for optimization, since you can still change it
In C++, but not neccessarily in D!?! There simply shouldn't be a const_cast<>() and you should restrict const parameters not to alias with other non const parameters. Are there any other problems? I don't know if "mutable" could cause problems, if D would get something like this.
4) in my experience, it has never found a bug for me
It has for me.
Feb 12 2004
prev sibling next sibling parent reply "Richard Krehbiel" <rich kastle.com> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into the
 original variable?
Um, no. The caller and called function do not both execute concurrently by multithreading. It's just a function call. (If you like, the caller is "suspended" until the called function returns - but it's definitely not as formal as that.)
 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather suggest
 "ref", because what is happening is passing a parameter by reference.
It's enough to say that the adjusted value of any "inout" parameters are visible when the function returns. The caller can't tell exactly when it happens (and indeed it doesn't matter) because it's not running.
Oct 03 2002
next sibling parent reply Mac Reiter <Mac_member pathlink.com> writes:
In article <anhbkc$iah$1 digitaldaemon.com>, Richard Krehbiel says...
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into the
 original variable?
Um, no. The caller and called function do not both execute concurrently by multithreading. It's just a function call. (If you like, the caller is
"suspended" until the called function returns - but it's definitely not as
formal as that.)

 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather suggest
 "ref", because what is happening is passing a parameter by reference.
It's enough to say that the adjusted value of any "inout" parameters are visible when the function returns. The caller can't tell exactly when it happens (and indeed it doesn't matter) because it's not running.
Say the code has an array, then it creates two threads, and each of those threads calls a function, passing the single array through an inout array parameter. You now have two threads of execution, each of which is accessing something that is nominally the same array. The difference between "pass by reference" and "pass by copy/copyback" will be very obvious here. If the functions accepted the array by reference, then each thread will be able to immediately see changes being made to the array by the other thread (to within register caching or optimization limits -- I think array lookups count as pointer accesses and disable optimization, so we'll ignore this possibility for now). If the functions received a copy of the array, and will then copy their results back over the original array when they exit, then neither thread will see the work being done by the other thread (and race conditions are quite entertaining, since the first thread to return from this function call will have all of its results overwritten by the slower thread). If you are taking a large problem array and slicing it into multiple threads to take advantage of SMP, you will probably pass the entire array to each thread, along with parameters to specify which part of the problem that thread should be working on. Such a design will work with "pass by reference", but will fail completely with "pass by copy/copyback". I always assumed that "inout" parameters (arrays or otherwise) were passed by reference, purely from a performance standpoint. "pass by copy/copyback" hasn't really been used (to my knowledge) in a long time. I prefer pass by reference, both for performance and for correctness. I agree that it should be documented, since it can make a very real difference, in very real programming problems. I don't have a major problem with inout. You might consider using "alias" instead, since you already have "alias" as a way to represent one variable/expression under a different name, which is exactly what an inout parameter does (it aliases the actual parameter under the formal parameter name. Hopefully I got my ComSci terms correct there ;-). I'm not sure which side of the "one syntax == one semantics" argument this "alias" usage would fall on. I could argue it either way myself. Anyway, change or don't change as you see necessary. Definitely document exactly what it does. And always remember that multithreading changes almost everything about any statement along the lines of "it doesn't matter, because it is equivalent behavior whether it is executed at point A or at point B". And true SMP machines cause even more confusion, since they can actually mess with shared memory in the middle of a single instruction (if the instruction is "complicated" enough, usually meaning that it involves more than one memory access). Food for thought, Mac
Oct 03 2002
parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
"Mac Reiter" <Mac_member pathlink.com> wrote in message
news:anhn8t$u1o$1 digitaldaemon.com...
 In article <anhbkc$iah$1 digitaldaemon.com>, Richard Krehbiel says...
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
Um, no. The caller and called function do not both execute concurrently
by
multithreading.  It's just a function call.  (If you like, the caller is
"suspended" until the called function returns - but it's definitely not as
formal as that.)

 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by reference.
It's enough to say that the adjusted value of any "inout" parameters are visible when the function returns. The caller can't tell exactly when it happens (and indeed it doesn't matter) because it's not running.
Say the code has an array, then it creates two threads, and each of those threads calls a function, passing the single array through an inout array parameter. You now have two threads of execution, each of which is
accessing
 something that is nominally the same array.  The difference between "pass
by
 reference" and "pass by copy/copyback"
I'm not sure that considering "pass by copy/copyback" is worth worrying about AFAIK only very old fortran compiler use this instead of "pass by reference" or "pass by address" many languages, Perl for instance allows arrays to be "pass by copy", but no write back and C++ allows objects to be "pass by copy" again no write back. I agree with the original post that 'inout' should be 'ref' or 'byref' and also think that for arrays you should have 'byval' when you want to pass a copy (that is not copy/writeback) just copy. however I have started to become conserned about Walters comments somewhere else about arrays supporting copy-on-write operations. if two threads have a reference to an array, one modifies the array, will the other ALWAYS see the modifications or will it possibly see the old array ? Mike.
Oct 03 2002
next sibling parent reply Mac Reiter <Mac_member pathlink.com> writes:
Sorry.  No new info here.  But when I did my original reply, something wiped out
the subject line, so my reply ended up just "Re:", and then a reply to that
became "Re: Re:".  That didn't seem terribly useful to me, so I wanted to fix
the subject line for further threading...

Mac

In article <anhq2l$12k2$1 digitaldaemon.com>, Mike Wynn says...
"Mac Reiter" <Mac_member pathlink.com> wrote in message
news:anhn8t$u1o$1 digitaldaemon.com...
 In article <anhbkc$iah$1 digitaldaemon.com>, Richard Krehbiel says...
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
Um, no. The caller and called function do not both execute concurrently
by
multithreading.  It's just a function call.  (If you like, the caller is
"suspended" until the called function returns - but it's definitely not as
formal as that.)

 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by reference.
It's enough to say that the adjusted value of any "inout" parameters are visible when the function returns. The caller can't tell exactly when it happens (and indeed it doesn't matter) because it's not running.
Say the code has an array, then it creates two threads, and each of those threads calls a function, passing the single array through an inout array parameter. You now have two threads of execution, each of which is
accessing
 something that is nominally the same array.  The difference between "pass
by
 reference" and "pass by copy/copyback"
I'm not sure that considering "pass by copy/copyback" is worth worrying about AFAIK only very old fortran compiler use this instead of "pass by reference" or "pass by address" many languages, Perl for instance allows arrays to be "pass by copy", but no write back and C++ allows objects to be "pass by copy" again no write back. I agree with the original post that 'inout' should be 'ref' or 'byref' and also think that for arrays you should have 'byval' when you want to pass a copy (that is not copy/writeback) just copy. however I have started to become conserned about Walters comments somewhere else about arrays supporting copy-on-write operations. if two threads have a reference to an array, one modifies the array, will the other ALWAYS see the modifications or will it possibly see the old array ? Mike.
Oct 03 2002
parent reply Mac Reiter <Mac_member pathlink.com> writes:
In article <anhq2l$12k2$1 digitaldaemon.com>, Mike Wynn says...
"Mac Reiter" <Mac_member pathlink.com> wrote in message
news:anhn8t$u1o$1 digitaldaemon.com...
 In article <anhbkc$iah$1 digitaldaemon.com>, Richard Krehbiel says...
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
Um, no. The caller and called function do not both execute concurrently
by
multithreading.  It's just a function call.  (If you like, the caller is
"suspended" until the called function returns - but it's definitely not as
formal as that.)

 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by reference.
It's enough to say that the adjusted value of any "inout" parameters are visible when the function returns. The caller can't tell exactly when it happens (and indeed it doesn't matter) because it's not running.
Say the code has an array, then it creates two threads, and each of those threads calls a function, passing the single array through an inout array parameter. You now have two threads of execution, each of which is
accessing
 something that is nominally the same array.  The difference between "pass
by
 reference" and "pass by copy/copyback"
I'm not sure that considering "pass by copy/copyback" is worth worrying about AFAIK only very old fortran compiler use this instead of "pass by reference" or "pass by address" many languages, Perl for instance allows arrays to be "pass by copy", but no write back and C++ allows objects to be "pass by copy" again no write back.
I have recently been informed by one of my coworkers that Windows device driver development does make use of the copy/copyback. It is not always used, but there are situations where it is, and apparently they happen frequently enough to be built into the tools. Since D is meant to be a systems programming language, I suspect that similar issues will arise. While I could make the argument that "inout" would be good for copy/copyback and "ref" or "alias" would be good for referencing, I dislike that from the "what will the average person do?" standpoint. The average user, seeing "in" and "out" will think of "inout" first. That means that (if "inout" is kept at all) it should behave the way most people need it to, which is fast by reference. Another word like "copyinout" might be more explicit (and less likely for a novice to choose). As before, I don't have a strong preference between "inout", "ref", and "alias" for the more common reference case. Boy, did we wander a long way from the simple "request for documentation clarification" that started this thread... Mac
Oct 03 2002
parent "Mike Wynn" <mike.wynn l8night.co.uk> writes:
 I have recently been informed by one of my coworkers that Windows device
driver
 development does make use of the copy/copyback.  It is not always used,
but
 there are situations where it is, and apparently they happen frequently
enough
 to be built into the tools.  Since D is meant to be a systems programming
 language, I suspect that similar issues will arise.
IMHO I don't think that this is a valid enough reason to implement copy/writeback calls especially as D supports array and structure assignment copy/writeback has enough hidden pit falls that I feel it should be performed manually if that is you true desire. i.e. create a copy, call function by params passed by ref, writeback my guess is that in device driver dev you would be likely to want to do synchronized(devicelock) { create a copy } call function by params passed by ref, synchronized(devicelock) { check writeback o.k. if so then writeback; } I would say support for CPU atomic read/write and read_modify_write is more important but like volatile the most robust solution is to have it as a storeage class and not an atomic statement Mike. ::getting even further off topic::
Oct 03 2002
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
news:anhq2l$12k2$1 digitaldaemon.com...
 if two threads have a reference to an array, one modifies the array, will
 the other ALWAYS see the modifications or will it possibly see the old
array
 ?
It'll always see the modifications.
Oct 03 2002
prev sibling parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"Richard Krehbiel" <rich kastle.com> wrote in message
news:anhbkc$iah$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
Um, no. The caller and called function do not both execute concurrently
by
 multithreading.  It's just a function call.  (If you like, the caller is
 "suspended" until the called function returns - but it's definitely not as
 formal as that.)
I know how function call works. And I mean, if you are, actually, explicitely, deliberately using *multithreading*. Or let me put in an other example: int global_var; void fn(inout int a, inout int b) { a = 3; printf("a = %d\n", a); printf("b = %d\n", b); printf("global_var = %d\n", global_var); } int main() { global_var = 2; fn(global_var, global_var); return 0; }
 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by reference.
It's enough to say that the adjusted value of any "inout" parameters are visible when the function returns.
It is not enough. The same variable can be seen through other inout parameters, pointers, global variables, function return values, etc.
Oct 07 2002
parent reply "Richard Krehbiel" <rich kastle.com> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:anrhrf$8v9$1 digitaldaemon.com...
 "Richard Krehbiel" <rich kastle.com> wrote in message
 news:anhbkc$iah$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
Um, no. The caller and called function do not both execute concurrently
by
 multithreading.  It's just a function call.  (If you like, the caller is
 "suspended" until the called function returns - but it's definitely not
as
 formal as that.)
I know how function call works. And I mean, if you are, actually, explicitely, deliberately using *multithreading*.
When explicitly using multithreading, the time(s) that the value get changes are indeterminite, unless you protect access to the resource using synchronization. One reason ( I suspect) it's called "inout" and not "ref" is that this is the terminology used by RPC (Remote Procedure Call) interfaces. In this case, the parameter is physically copied to some other machine, and when the function returns, the adjusted value is copied back. Proper use of "in", "out", and "inout" let you control the amount of data copied over the network. In this case, the values of "inout" parameters remain the same in the caller until they are unmarshalled when the call returns. By indicating that the value is "inout" it implies RPC semantics. "Ref" doesn't mean the same thing.
 Or let me put in an other example:

 int global_var;

 void fn(inout int a, inout int b)
 {
   a = 3;
   printf("a = %d\n", a);
   printf("b = %d\n", b);
   printf("global_var = %d\n", global_var);
 }

 int main()
 {
   global_var = 2;
   fn(global_var, global_var);
   return 0;
 }
In the absence of actual RPC, I'd expect "inout" to have "ref" semantics, which makes this a "simple" example of aliasing. And, BTW, I notice that this example isn't using multithreading. But I wonder if this is an important enough issue to make "ref" distinct from "inout." -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 comcast.net (personal)
Oct 07 2002
parent "Sandor Hojtsy" <hojtsy index.hu> writes:
"Richard Krehbiel" <rich kastle.com> wrote in message
news:ans2fd$qaj$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:anrhrf$8v9$1 digitaldaemon.com...
 "Richard Krehbiel" <rich kastle.com> wrote in message
 news:anhbkc$iah$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the
same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated
into
 the
 original variable?
Um, no. The caller and called function do not both execute
concurrently
 by
 multithreading.  It's just a function call.  (If you like, the caller
is
 "suspended" until the called function returns - but it's definitely
not
 as
 formal as that.)
I know how function call works. And I mean, if you are, actually, explicitely, deliberately using *multithreading*.
When explicitly using multithreading, the time(s) that the value get
changes
 are indeterminite, unless you protect access to the resource using
 synchronization.

 One reason ( I suspect) it's called "inout" and not "ref" is that this is
 the terminology used by RPC (Remote Procedure Call) interfaces.  In this
 case, the parameter is physically copied to some other machine, and when
the
 function returns, the adjusted value is copied back.  Proper use of "in",
 "out", and "inout" let you control the amount of data copied over the
 network.  In this case, the values of "inout" parameters remain the same
in
 the caller until they are unmarshalled when the call returns.  By
indicating
 that the value is "inout" it implies RPC semantics.  "Ref" doesn't mean
the
 same thing.
Exactlty. "ref" doesn't mean the same thing. And currently "inout" is doing what you should call "ref". Hmm, in some situations real "inout" could be useful, but I can live withouth it.
 Or let me put in an other example:

 int global_var;

 void fn(inout int a, inout int b)
 {
   a = 3;
   printf("a = %d\n", a);
   printf("b = %d\n", b);
   printf("global_var = %d\n", global_var);
 }

 int main()
 {
   global_var = 2;
   fn(global_var, global_var);
   return 0;
 }
In the absence of actual RPC, I'd expect "inout" to have "ref" semantics, which makes this a "simple" example of aliasing.
I would not expect it. The name tells just the opposite.
 And, BTW, I notice that
 this example isn't using multithreading.
Yes. I considered multithreading to be too complex example for this. And wanted to show, that you don't need multithreading to find out when the original parameter value is modified.
 But I wonder if this is an important enough issue to make "ref" distinct
 from "inout."
Don't make them distinct, rename the "inout" keyword! Sandor
Oct 07 2002
prev sibling next sibling parent reply "chris jones" <flak clara.co.uk> writes:
I also prefer 'ref' to inout, also i would like to so 'in' dropped as nobody
is ever going to use it, it is implicit and hence redundant. Its a waste of
ascii.

chris


"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into the
 original variable?
 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather suggest
 "ref", because what is happening is passing a parameter by reference.

 Sandor
Oct 03 2002
next sibling parent reply Mark Evans <Mark_member pathlink.com> writes:
Consistency is more important than a few keystrokes.  Contract qualifiers
document the code; 'in' should be just as mandatory (or just as optional) as the
other two.

Many languages have confused the issue of call-by-value and call-by-reference.
This situation makes 'ref' a bad term.  A better term is 'shared.' The parameter
is shared between caller and callee.

The term 'inout' is unhelpful.  It doesn't communicate what is actually
happening.  Something goes in, and something comes out, but 'inout' fails to
indicate that they are actually the *same* thing.

Beyond that the shared parameter might be unused and/or unchanged by the caller
(as an output) or callee (as an input).  So 'inout' wrongly connotes usage of,
and/or changes to, the parameter when they are in fact optional.  The term
'shared' has the right connotations.

Mark

In article <ani3ss$1djm$1 digitaldaemon.com>, chris jones says...
I also prefer 'ref' to inout, also i would like to so 'in' dropped as nobody
is ever going to use it, it is implicit and hence redundant. Its a waste of
ascii.

chris
Oct 03 2002
next sibling parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
"Mark Evans" <Mark_member pathlink.com> wrote in message
news:ani6po$1gr4$1 digitaldaemon.com...
 Consistency is more important than a few keystrokes.  Contract qualifiers
 document the code; 'in' should be just as mandatory (or just as optional)
as the
 other two.
'in' should either be droped or mandatory (do you ever use 'auto' in your c code?) Mike.
Oct 03 2002
next sibling parent Mark Evans <Mark_member pathlink.com> writes:
Mandatory then.  C does not pretend to be self-documenting or contract-based, so
the analogy with 'auto' is a broken one <g>.  Read the IMP posting about the
semantic problem in C regarding 'static'.  When the language itself is
inconsistent, you can't blame me for using it asymetrically.

C should be taken as a model for any language and D should do everything it can
to repair its many problems.

- Mark

In article <ani8iq$1j9q$1 digitaldaemon.com>, Mike Wynn says...
'in' should either be droped or mandatory (do you ever use 'auto' in your c
code?)
Oct 03 2002
prev sibling parent Mark Evans <Mark_member pathlink.com> writes:
(Typo, that was "C should NOT be taken as a model for any language..."

Mark)
Oct 03 2002
prev sibling parent reply "chris jones" <flak clara.co.uk> writes:
"Mark Evans" <Mark_member pathlink.com> wrote in message
news:ani6po$1gr4$1 digitaldaemon.com...
 Consistency is more important than a few keystrokes.  Contract qualifiers
 document the code; 'in' should be just as mandatory (or just as optional)
as the
 other two.
Im not sugesting 'in' should be optional and the others mandatory but that 'in' should not exist at all and out/inout mandatory. The fact that in is not specified can only mean one thing, that it is an 'in' parameter, therefore the omision of 'in' is just as specific as the inclusion of it. There is no question of consistency with this and hence no need to document it. Can you imagine a situation where sombody might be confused over this? I cant even imagine newbies finding it confusing.
 Many languages have confused the issue of call-by-value and
call-by-reference.
 This situation makes 'ref' a bad term.  A better term is 'shared.' The
parameter
 is shared between caller and callee.

 The term 'inout' is unhelpful.  It doesn't communicate what is actually
 happening.  Something goes in, and something comes out, but 'inout' fails
to
 indicate that they are actually the *same* thing.
Thats a very good point. chris
Oct 03 2002
parent reply Mark Evans <Mark_member pathlink.com> writes:
The fact that in is not specified can only mean one thing
No, it can mean whatever the programmer's previous language experience (or lack thereof) might suggest. Considering that 'in' need be written in only one place -- the function definition -- I don't think it's too much to ask for consistency's sake. Especially since we want D programmers to think in terms of contracts. Glad that you liked the 'shared' idea ;-). Mark
Oct 03 2002
next sibling parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
Some days I write more function declarations than actual code.  Prototyping.
So making function declarations more wordy will just hinder people.  In is
not necessary.

Sean

"Mark Evans" <Mark_member pathlink.com> wrote in message
news:anirhi$26cj$1 digitaldaemon.com...
The fact that in is not specified can only mean one thing
No, it can mean whatever the programmer's previous language experience (or
lack
 thereof) might suggest.

 Considering that 'in' need be written in only one place -- the function
 definition -- I don't think it's too much to ask for consistency's sake.
 Especially since we want D programmers to think in terms of contracts.

 Glad that you liked the 'shared' idea ;-).

 Mark
Oct 03 2002
parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
in C/C++ you have to write all function defs twice (one in .h one in .cpp),
in D its only once, so you've saved all those chars, is a few in's realy
that much more typing.


"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
news:anj7mk$2ibr$1 digitaldaemon.com...
 Some days I write more function declarations than actual code.
Prototyping.
 So making function declarations more wordy will just hinder people.  In is
 not necessary.

 Sean

 "Mark Evans" <Mark_member pathlink.com> wrote in message
 news:anirhi$26cj$1 digitaldaemon.com...
The fact that in is not specified can only mean one thing
No, it can mean whatever the programmer's previous language experience
(or
 lack
 thereof) might suggest.

 Considering that 'in' need be written in only one place -- the function
 definition -- I don't think it's too much to ask for consistency's sake.
 Especially since we want D programmers to think in terms of contracts.

 Glad that you liked the 'shared' idea ;-).

 Mark
Oct 04 2002
parent "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
Yes.

I just won all those chars back from C++, do you think I'm just going to
give them away that easily? ;)

Sean

"Mike Wynn" <mike.wynn l8night.co.uk> wrote in message
news:ankl33$118o$1 digitaldaemon.com...
 in C/C++ you have to write all function defs twice (one in .h one in
.cpp),
 in D its only once, so you've saved all those chars, is a few in's realy
 that much more typing.


 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:anj7mk$2ibr$1 digitaldaemon.com...
 Some days I write more function declarations than actual code.
Prototyping.
 So making function declarations more wordy will just hinder people.  In
is
 not necessary.

 Sean

 "Mark Evans" <Mark_member pathlink.com> wrote in message
 news:anirhi$26cj$1 digitaldaemon.com...
The fact that in is not specified can only mean one thing
No, it can mean whatever the programmer's previous language experience
(or
 lack
 thereof) might suggest.

 Considering that 'in' need be written in only one place -- the
function
 definition -- I don't think it's too much to ask for consistency's
sake.
 Especially since we want D programmers to think in terms of contracts.

 Glad that you liked the 'shared' idea ;-).

 Mark
Oct 04 2002
prev sibling parent Matthias Becker <Matthias_member pathlink.com> writes:
The fact that in is not specified can only mean one thing
No, it can mean whatever the programmer's previous language experience (or lack thereof) might suggest.
Isn't this true for any keyword? You have to learn the language, before using it.
Feb 12 2004
prev sibling next sibling parent reply "Walter" <walter digitalmars.com> writes:
"chris jones" <flak clara.co.uk> wrote in message
news:ani3ss$1djm$1 digitaldaemon.com...
 I also prefer 'ref' to inout, also i would like to so 'in' dropped as
nobody
 is ever going to use it, it is implicit and hence redundant. Its a waste
of
 ascii.
That's probably a good idea.
Oct 03 2002
parent Matthias Becker <Matthias_member pathlink.com> writes:
 I also prefer 'ref' to inout, also i would like to so 'in' dropped as
nobody
 is ever going to use it, it is implicit and hence redundant. Its a waste
of
 ascii.
That's probably a good idea.
Either I'm stupid or this suggestion was part of my first (or second?) post here. :confused:
Feb 12 2004
prev sibling parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
I agree with both points.  Ref makes more sense and it's the term that most
people are used to for the concept.  In is just a waste, adds bloat but no
clarity.  Makes a good default.  Perhaps we can reuse the "return" keyword
instead of adding a new one "out".

Probably too late to worry about this one, alot of people are probably
attached to the in/out/inout scheme.  What D has now isn't really broken.

Sean

"chris jones" <flak clara.co.uk> wrote in message
news:ani3ss$1djm$1 digitaldaemon.com...
 I also prefer 'ref' to inout, also i would like to so 'in' dropped as
nobody
 is ever going to use it, it is implicit and hence redundant. Its a waste
of
 ascii.

 chris
Oct 03 2002
next sibling parent reply Mark Evans <Mark_member pathlink.com> writes:
This minor D topic is getting more press than it deserves, however my comments
may elucidate some philosophical issues that will help in many other areas.


1a. Talk to more software managers and functional specification people in the
corporate and military worlds.  They are not fond of "implicit" things that "you
are just supposed to know."  I would not be surprised if they used
commented '/*in*/' everywhere.

1b. Minimum-ascii thinking led to the horrible C syntax and butchered semantics
that we have today.  Remember when you were first learning C?  I do.  It was
awful.  Everything was so cryptic.

2. Talk to non-C programmers and novices.  They will give you all kinds of weird
ideas about call-by-reference and call-by-value.  Maybe D will never be used by
non-C programmers, but I sure hope it will.

3. Recent posts suggest special cases in D (array objects) where call-by-value
is not the default.  So now what you are "just supposed to know" starts
encompassing various special cases for your memorization pleasure.

4. I dislike 'ref' because it might as well just be '&'.  The in/out stuff is
about contracts, and C has no such concept.  D should use a word that has
something to do with contracts -- and conversely, there should be *no* direct
translation into any C keyword or concept.  I'll take 'inout' over 'ref' any
day.  Be consistent.  If we use 'ref', then we are now using a term that
describes the technical implementation, not the contract.  So logically it
follows that 'in' should become 'pushed-stack' and 'out' should become
'popped-stack'. Yuk!

Mark


In article <anj7bn$2hvt$1 digitaldaemon.com>, Sean L. Palmer says...
I agree with both points.  Ref makes more sense and it's the term that most
people are used to for the concept.  In is just a waste, adds bloat but no
clarity.  Makes a good default.  Perhaps we can reuse the "return" keyword
instead of adding a new one "out".

Probably too late to worry about this one, alot of people are probably
attached to the in/out/inout scheme.  What D has now isn't really broken.

Sean

"chris jones" <flak clara.co.uk> wrote in message
news:ani3ss$1djm$1 digitaldaemon.com...
 I also prefer 'ref' to inout, also i would like to so 'in' dropped as
nobody
 is ever going to use it, it is implicit and hence redundant. Its a waste
of
 ascii.

 chris
Oct 03 2002
next sibling parent reply "Walter" <walter digitalmars.com> writes:
Lots of great comments! Here are some of mine:

1) IDL already uses in, out, and inout. I've seen many people use /*in*/,
etc.

2) Many D type are implicitly passed by reference not by value (such as
class objects). Having a 'ref' keyword may thoroughly confuse the issue.

3) Having 'inout' to me means that a value is passed in, and then possibly
modified by the function.

4) I wished to abandon the C++ & reference notation, because it was used for
3 different purposes:
    a) runtime efficiency
    b) to initialized the caller variable
    c) to reset the caller variable
To know which it is, you have to consult the documentation which is always
wrong, ambiguous, or missing.

5) In D, the distinctions between a, b, c are clear (or at least clear
enough that an extra IDL layer is not needed). The whole existence of IDL is
to cover a basic failing of C++.

6) Sure the 'in' is redundant - but some redundancy is good for reducing
typo errors. 'in' is there for the (many) programmers who like to use /*in*/
and would like some language support for their style. 'in' is optional (I
don't use it myself), and is harmless enough if you don't want to use it.
Oct 04 2002
parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
I just don't want 'in' becoming mandatory.  ;)

Sean

"Walter" <walter digitalmars.com> wrote in message
news:anjev9$2qq0$1 digitaldaemon.com...

 6) Sure the 'in' is redundant - but some redundancy is good for reducing
 typo errors. 'in' is there for the (many) programmers who like to use
/*in*/
 and would like some language support for their style. 'in' is optional (I
 don't use it myself), and is harmless enough if you don't want to use it.
Oct 04 2002
parent reply "Walter" <walter digitalmars.com> writes:
Don't worry, I won't do that <g>. Requiring it would mean that 'in's would
become as ubiquitous as 'const' in C++ parameter lists, and would be just as
distracting (to me, anyway).

"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
news:ankih8$uhi$1 digitaldaemon.com...
 I just don't want 'in' becoming mandatory.  ;)

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:anjev9$2qq0$1 digitaldaemon.com...

 6) Sure the 'in' is redundant - but some redundancy is good for reducing
 typo errors. 'in' is there for the (many) programmers who like to use
/*in*/
 and would like some language support for their style. 'in' is optional
(I
 don't use it myself), and is harmless enough if you don't want to use
it.

Oct 04 2002
parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
Maybe parameters should never be writable, unless you explicitly say it
should be.  Disallow writes to in parameters even inside the function.  Then
by default it's reference, except for small types.  And if the callee wants
to modify it he must do the copy (or cast) client-side.  And callers can
rest assured the parameters they're sending are sort of guaranteed (barring
casts) not to allow callees to alter their "in" parameters.  Certainly this
would be a great boon to compiler optimization.

in other words I want to make this illegal:

uint strlen(char* s)
{
    // uint len=0; while (*s++) ++len; return len;  // error... can't modify
parameter "s"
    uint len=0; char* scan = s; while (*scan++) ++len; return len; } // ok
}

void zero(char* s)
{
    *s = 0;  // this is ok, writing thru pointer parameter.
}

Writing to out parameters should be ok.

Sean

"Walter" <walter digitalmars.com> wrote in message
news:ankrnc$18pl$2 digitaldaemon.com...
 Don't worry, I won't do that <g>. Requiring it would mean that 'in's would
 become as ubiquitous as 'const' in C++ parameter lists, and would be just
as
 distracting (to me, anyway).

 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:ankih8$uhi$1 digitaldaemon.com...
 I just don't want 'in' becoming mandatory.  ;)

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:anjev9$2qq0$1 digitaldaemon.com...

 6) Sure the 'in' is redundant - but some redundancy is good for
reducing
 typo errors. 'in' is there for the (many) programmers who like to use
/*in*/
 and would like some language support for their style. 'in' is optional
(I
 don't use it myself), and is harmless enough if you don't want to use
it.

Oct 05 2002
next sibling parent reply "Walter" <walter digitalmars.com> writes:
If the parameter is call by reference, like a class object, then even if the
function copies the parameter to a local so he can modify it, he still will
be modifying the referred to type. I don't understand the advantage here.

"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
news:anm3km$2g7p$1 digitaldaemon.com...
 Maybe parameters should never be writable, unless you explicitly say it
 should be.  Disallow writes to in parameters even inside the function.
Then
 by default it's reference, except for small types.  And if the callee
wants
 to modify it he must do the copy (or cast) client-side.  And callers can
 rest assured the parameters they're sending are sort of guaranteed
(barring
 casts) not to allow callees to alter their "in" parameters.  Certainly
this
 would be a great boon to compiler optimization.

 in other words I want to make this illegal:

 uint strlen(char* s)
 {
     // uint len=0; while (*s++) ++len; return len;  // error... can't
modify
 parameter "s"
     uint len=0; char* scan = s; while (*scan++) ++len; return len; } // ok
 }

 void zero(char* s)
 {
     *s = 0;  // this is ok, writing thru pointer parameter.
 }

 Writing to out parameters should be ok.

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:ankrnc$18pl$2 digitaldaemon.com...
 Don't worry, I won't do that <g>. Requiring it would mean that 'in's
would
 become as ubiquitous as 'const' in C++ parameter lists, and would be
just
 as
 distracting (to me, anyway).

 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:ankih8$uhi$1 digitaldaemon.com...
 I just don't want 'in' becoming mandatory.  ;)

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:anjev9$2qq0$1 digitaldaemon.com...

 6) Sure the 'in' is redundant - but some redundancy is good for
reducing
 typo errors. 'in' is there for the (many) programmers who like to
use
 /*in*/
 and would like some language support for their style. 'in' is
optional
 (I
 don't use it myself), and is harmless enough if you don't want to
use
 it.

Oct 05 2002
parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
It means the compiler can safely decide whether to pass by reference or by
value based only upon performance considerations (for in parameters) since
the callee is "guaranteed" not to alter it.

Sean

"Walter" <walter digitalmars.com> wrote in message
news:ann6h0$1c57$2 digitaldaemon.com...
 If the parameter is call by reference, like a class object, then even if
the
 function copies the parameter to a local so he can modify it, he still
will
 be modifying the referred to type. I don't understand the advantage here.

 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:anm3km$2g7p$1 digitaldaemon.com...
 Maybe parameters should never be writable, unless you explicitly say it
 should be.  Disallow writes to in parameters even inside the function.
Then
 by default it's reference, except for small types.  And if the callee
wants
 to modify it he must do the copy (or cast) client-side.  And callers can
 rest assured the parameters they're sending are sort of guaranteed
(barring
 casts) not to allow callees to alter their "in" parameters.  Certainly
this
 would be a great boon to compiler optimization.

 in other words I want to make this illegal:

 uint strlen(char* s)
 {
     // uint len=0; while (*s++) ++len; return len;  // error... can't
modify
 parameter "s"
     uint len=0; char* scan = s; while (*scan++) ++len; return len; } //
ok
 }

 void zero(char* s)
 {
     *s = 0;  // this is ok, writing thru pointer parameter.
 }

 Writing to out parameters should be ok.

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:ankrnc$18pl$2 digitaldaemon.com...
 Don't worry, I won't do that <g>. Requiring it would mean that 'in's
would
 become as ubiquitous as 'const' in C++ parameter lists, and would be
just
 as
 distracting (to me, anyway).

 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:ankih8$uhi$1 digitaldaemon.com...
 I just don't want 'in' becoming mandatory.  ;)

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:anjev9$2qq0$1 digitaldaemon.com...

 6) Sure the 'in' is redundant - but some redundancy is good for
reducing
 typo errors. 'in' is there for the (many) programmers who like to
use
 /*in*/
 and would like some language support for their style. 'in' is
optional
 (I
 don't use it myself), and is harmless enough if you don't want to
use
 it.

Oct 05 2002
parent "Walter" <walter digitalmars.com> writes:
Ok, I see what you're talking about. -Walter

"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
news:annk04$1q6b$1 digitaldaemon.com...
 It means the compiler can safely decide whether to pass by reference or by
 value based only upon performance considerations (for in parameters) since
 the callee is "guaranteed" not to alter it.

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:ann6h0$1c57$2 digitaldaemon.com...
 If the parameter is call by reference, like a class object, then even if
the
 function copies the parameter to a local so he can modify it, he still
will
 be modifying the referred to type. I don't understand the advantage
here.
 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:anm3km$2g7p$1 digitaldaemon.com...
 Maybe parameters should never be writable, unless you explicitly say
it
 should be.  Disallow writes to in parameters even inside the function.
Then
 by default it's reference, except for small types.  And if the callee
wants
 to modify it he must do the copy (or cast) client-side.  And callers
can
 rest assured the parameters they're sending are sort of guaranteed
(barring
 casts) not to allow callees to alter their "in" parameters.  Certainly
this
 would be a great boon to compiler optimization.

 in other words I want to make this illegal:

 uint strlen(char* s)
 {
     // uint len=0; while (*s++) ++len; return len;  // error... can't
modify
 parameter "s"
     uint len=0; char* scan = s; while (*scan++) ++len; return len; }
//
 ok
 }

 void zero(char* s)
 {
     *s = 0;  // this is ok, writing thru pointer parameter.
 }

 Writing to out parameters should be ok.

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:ankrnc$18pl$2 digitaldaemon.com...
 Don't worry, I won't do that <g>. Requiring it would mean that 'in's
would
 become as ubiquitous as 'const' in C++ parameter lists, and would be
just
 as
 distracting (to me, anyway).

 "Sean L. Palmer" <seanpalmer directvinternet.com> wrote in message
 news:ankih8$uhi$1 digitaldaemon.com...
 I just don't want 'in' becoming mandatory.  ;)

 Sean

 "Walter" <walter digitalmars.com> wrote in message
 news:anjev9$2qq0$1 digitaldaemon.com...

 6) Sure the 'in' is redundant - but some redundancy is good for
reducing
 typo errors. 'in' is there for the (many) programmers who like
to
 use
 /*in*/
 and would like some language support for their style. 'in' is
optional
 (I
 don't use it myself), and is harmless enough if you don't want
to
 use
 it.

Oct 07 2002
prev sibling parent Burton Radons <loth users.sourceforge.net> writes:
Sean L. Palmer wrote:
 Maybe parameters should never be writable, unless you explicitly say it
 should be.  Disallow writes to in parameters even inside the function.  Then
 by default it's reference, except for small types.  And if the callee wants
 to modify it he must do the copy (or cast) client-side.  And callers can
 rest assured the parameters they're sending are sort of guaranteed (barring
 casts) not to allow callees to alter their "in" parameters.  Certainly this
 would be a great boon to compiler optimization.
Use an inout parameter. It doesn't matter if it's generated on the stack like a return from a function call - our compilers should be getting more savvy about constructing stack objects anyway (stack arrays are the next big thing), and should be able to provide a pointer to them. Not really an anything to optimisation. Memory caching is the problem here; the fewer distinct memory scopes in a function the better. So if the function is complex and the caller isn't passing a pointer to a stack object (say, a class object member), I'd bet it would be faster to pass on the stack. What could happen is that it could pass a pointer if the parameter is explicitly "in" and if the object is on the stack, but copy it onto the stack if it's coming from elsewhere in memory. There's no point in testing it in DLI right now due to its sucking.
Oct 05 2002
prev sibling parent Matthias Becker <Matthias_member pathlink.com> writes:
1b. Minimum-ascii thinking led to the horrible C syntax and butchered semantics
that we have today.  Remember when you were first learning C?  I do.  It was
awful.  Everything was so cryptic.
MAIN mAIn Ma1N MAIN ma1N mA1N mAiN Ma1N MA1N ma1N mA1N maIn MaIN malN mA1N ma1n mA1N maiN Main MAIN main Ma1N MAIN Ma1n mA1N MA1N maIN mAin mAlN Ma1n MAlN mAIN Main maIn MaIn mA1N Ma1n maln mAin MaIn Main maIn MaIN mAiN Ma1N Ma1N Ma1n maln maIN mAin MaIn ma1N ma1N Main ma1n MaIN mAiN Ma1N Ma1N Ma1n maln maIN mAin MaIn ma1N ma1N Main mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N mAIn Ma1N Ma1n ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N ma1N Main MAin mA1N maiN ma1N Main mAIN Main MAIn MAIN mAIn Ma1N MAIN mAin ma1N MaiN MAIN main MaIN malN Main main MaIn Main mAIN mA1N maiN MalN Ma1N MAiN maIn mAln main ma1N MA1n Ma1N MAiN ma1n mAln main ma1N MA1n mAin MAln Ma1N mA1n MAiN ma1n mAln main MAln mAin ma1N ma1N ma1N MAln Ma1N mA1n MAiN maIn mAln main MAln Ma1N MAiN ma1n mAln main ma1N MA1n mAin MAln Ma1N mA1n MAiN ma1n mAln main MAln mAin ma1N ma1N ma1N ma1N ma1N ma1N Maln main mA1N MAiN ma1n mAln main MAln mAin ma1N MA1n MAiN maIn mAln main MAln Ma1N MAiN ma1n mAln main ma1N MA1n mAin MAln Ma1N mA1n MAiN ma1n mAln main MAln mAin ma1N ma1N ma1N ma1N Main MAIn
Feb 12 2004
prev sibling parent Matthias Becker <Matthias_member pathlink.com> writes:
Probably too late to worry about this one, alot of people are probably
attached to the in/out/inout scheme.  What D has now isn't really broken.
D still hasn't reached version 1.0, so this shouldn't be a problem.
Feb 12 2004
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into the
 original variable?
 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather suggest
 "ref", because what is happening is passing a parameter by reference.
inout is also used by IDL, and so is familiar to many C/C++ programmers.
Oct 03 2002
parent reply Mac Reiter <Mac_member pathlink.com> writes:
In article <aniq73$2522$1 digitaldaemon.com>, Walter says...
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into the
 original variable?
 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather suggest
 "ref", because what is happening is passing a parameter by reference.
inout is also used by IDL, and so is familiar to many C/C++ programmers.
Sorry I'm kinda late on this -- didn't get to read Friday afternoon or over weekend. As a not of interest, inout in the IDL context is more precise. Since IDL is used for interfaces that may be used on RPC or network marshalled function calls, copy/copyback is a very reasonable implementation. Even if you are on the same machine (COM instead of DCOM or CORBA), the interface may belong to an out-of-process server, which means you can't (easily) just hand a reference across the interface boundary. Not a huge deal for normal D programming, or even for DLL programming in D, but if you start looking at full COM/DCOM/CORBA/.NET support, then the differences between copy/copyback and reference-passing will become more obvious. Mac
Oct 07 2002
parent "Sandor Hojtsy" <hojtsy index.hu> writes:
"Mac Reiter" <Mac_member pathlink.com> wrote in message
news:ans5h2$trt$1 digitaldaemon.com...
 In article <aniq73$2522$1 digitaldaemon.com>, Walter says...
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:angu34$4ba$1 digitaldaemon.com...
 Consider passing a value as "inout" parameter to a function.
 Then both the caller and the called functions continue to use the same
 value, by multithreading.
 Now when will the changes of the inout parameter be incorporated into
the
 original variable?
 Immediately, or when the called function returns?
 The specification does not tell. (Walter: please put it in)
 The "inout" name suggests the later, but the first happens (i hope).
 Therefore the name "inout" is not really intuitive. I would rather
suggest
 "ref", because what is happening is passing a parameter by reference.
inout is also used by IDL, and so is familiar to many C/C++ programmers.
As a not of interest, inout in the IDL context is more precise. Since IDL
is
 used for interfaces that may be used on RPC or network marshalled function
 calls, copy/copyback is a very reasonable implementation.
So you adopted the keyword, with a different meaning. Do you think guys with IDL knowledge will be happy? I find "inout" a good name for copy/copyback, but not for call by reference. Sandor
Oct 07 2002