May 25, 2004
On Tue, 25 May 2004 08:44:21 +0200, Norbert Nemec wrote:

> Then this boils down to the good old war about "const". Walter decided to make "const" a storage class, not a type modifier. This means, we have const objects, you can take a pointer from them, but then the compiler does not help you in tracking that they were const.
> 
> Introducing "ref" in addition to "inout" would just hide this fact in a very obscure way. "inout mytype arg" would be "mytype &arg" in C++, while "ref mytype arg" would be "const mytype &arg".
> 
> I believe that whole business of "in", "out" and "inout" arguments is flawed. My first expectation, when I saw these was, that that they are "copy-in/copy-out" arguments. The specs are not very precise when they talk about this question. Somehow, I have the feeling, that D tries to hide the complexity of reference/value arguments from the user, but, at the same time, obscures and cripples the concept completely.
> 
> My opinion: neither the C++ nor the D way are the solution. I don't know the solution, but it has to be out there somewhere.

See below ...

> Kris wrote:
> 
>> One cannot use 'inout' with a const struct, since by definition it's read-only.
>> 
>> - Kris
>> 
>> "Carlos Santander B." <carlos8294@msn.com> wrote in message news:c8udnv$205u$1@digitaldaemon.com...
>>> "imr1984" <imr1984_member@pathlink.com> escribió en el mensaje
>>> news:c8tbvq$fm$1@digitaldaemon.com
>>> | I think D needs a 'ref' keyword like C# has. This way large structs can
>> be
>>> | passed by reference without nasty pointers. The way i see it, this is
>> the
>>> only
>>> | way to support this because as Stewart says if you have a function
>>> exported from
>>> | a library, and it takes a struct, the only way for the compiler to know
>>> that the
>>> | exported func takes the struct by Ref is if its indicated in the
>> prototype
>>> with
>>> | the ref keyword.
>>> |
>>>
>>> What's wrong with inout?
>>>
>>> -----------------------
>>> Carlos Santander Bernal
>>>
>>>

Now I know that D needs to be almost as fast as raw assembler code, so the method I'm about to describe will not be useful in all cases for D, but it is another way of thinking about parameter passing...

In another language that I use a great deal, all parameters are passed by value (semantically). In this language, there are only two effective data types - numbers and vectors. As vectors can be arbitarily large, they are actually passed by reference but on the first write to a vector parameter, the language automatically does a copy of it and changes the reference to point to the copy. It's actually a bit more sophisticated than that, but the net effect from the coder's point of view is that you can never alter a variable being passed as a parameter from within the function being called. Also, the automatic copy-on-write feature makes this 'pass by value' fairly efficient. BTW it also does automatic garbage collection for you too.

For example (not quality code but just an example!):
  function ToUpper(sequence x)
      for i = 1 to length(x) do
           if x[i] >= 'a' and x[i] <= 'z' then
	           x[i] = x[i] + ('A' - 'a')
           end if
      end for
      return x
  end function

  sequence A, B
  A = "abc"
  B = ToUpper(A)

After the call to ToUpper(), 'A' will still be "abc" and 'B' will be "ABC".
In fact, if you needed to update 'A' you would code 'A = ToUpper(A)'.

-- 
Derek
25/May/04 5:18:36 PM
May 25, 2004
Norbert Nemec wrote:

<snip>
> I believe that whole business of "in", "out" and "inout" arguments is
> flawed. My first expectation, when I saw these was, that that they are
> "copy-in/copy-out" arguments. The specs are not very precise when they talk
> about this question. Somehow, I have the feeling, that D tries to hide the
> complexity of reference/value arguments from the user, but, at the same
> time, obscures and cripples the concept completely.
> 
> My opinion: neither the C++ nor the D way are the solution. I don't know the
> solution, but it has to be out there somewhere.
<snip top of upside-down reply>

Maybe in should've meant pass by reference, making it like out/inout, leaving no modifier to mean pass by value.  At least as far as structs and atomic types go, don't ask me about arrays, obects and the like....

Stewart.

-- 
My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment.  Please keep replies on the 'group where everyone may benefit.
May 25, 2004
inout for a readonly parameter is inaccurate and misleading.

Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.

In article <c8udnv$205u$1@digitaldaemon.com>, Carlos Santander B. says...
>
>"imr1984" <imr1984_member@pathlink.com> escribió en el mensaje
>news:c8tbvq$fm$1@digitaldaemon.com
>| I think D needs a 'ref' keyword like C# has. This way large structs can be
>| passed by reference without nasty pointers. The way i see it, this is the
>only
>| way to support this because as Stewart says if you have a function
>exported from
>| a library, and it takes a struct, the only way for the compiler to know
>that the
>| exported func takes the struct by Ref is if its indicated in the prototype
>with
>| the ref keyword.
>|
>
>What's wrong with inout?
>
>-----------------------
>Carlos Santander Bernal
>
>


May 25, 2004
imr1984 wrote:

> inout for a readonly parameter is inaccurate and misleading.
> 
> Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.

Sounds like a good solution! I really like that! 'in' would be the same thing as 'const &' in C++. No semantic difference to the current situation (except in the case where another function changes the data behind the reference while the called function is running but that is dangerous in any case). Just a clean way to tell the compiler what the calling convention for a given function should be (Which is an information that the compiler cannot easily deduct automatically).

May 25, 2004
In article <c8vhji$tkh$1@digitaldaemon.com>, Norbert Nemec says...
>
>imr1984 wrote:
>
>> inout for a readonly parameter is inaccurate and misleading.
>> 
>> Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.
>
>Sounds like a good solution! I really like that! 'in' would be the same thing as 'const &' in C++. No semantic difference to the current situation (except in the case where another function changes the data behind the reference while the called function is running but that is dangerous in any case). Just a clean way to tell the compiler what the calling convention for a given function should be (Which is an information that the compiler cannot easily deduct automatically).
>

exactly :)


May 25, 2004
imr1984 wrote:

> inout for a readonly parameter is inaccurate and misleading. 
> 
> Or - here is an idea - Since no one actually uses the 'in' keyword, why not make
> the in keyword explicitly mean pass by reference, and the function is not
> allowed to write to the pointer. This would be perfect.

You would need to make sure that 'in' references are only passed to methods as 'in' arguments, and so on and so forth.

It's C++ const all over again.

What might be better is if the ABI said that all structs are always passed by reference.  In the case of 'in' parameters, the compiler would be responsible for creating a temporary copy if one is needed. (ie if it thinks the struct is written to)

Are there any arguments for passing structs by value?

 -- andy
May 25, 2004
In article <c8vnlv$17f4$1@digitaldaemon.com>, Andy Friesen says...
>
>imr1984 wrote:
>
>> inout for a readonly parameter is inaccurate and misleading.
>> 
>> Or - here is an idea - Since no one actually uses the 'in' keyword, why not make the in keyword explicitly mean pass by reference, and the function is not allowed to write to the pointer. This would be perfect.
>
>You would need to make sure that 'in' references are only passed to methods as 'in' arguments, and so on and so forth.
>
>It's C++ const all over again.
>
>What might be better is if the ABI said that all structs are always passed by reference.  In the case of 'in' parameters, the compiler would be responsible for creating a temporary copy if one is needed. (ie if it thinks the struct is written to)
>
>Are there any arguments for passing structs by value?
>
>  -- andy

Andy that would also work very well - No I cant think of single reason why you would want to pass a struct by value. I wish the spec was more clear on what actually happens under the hood with regards to parameter passing.

So I guess that kinda makes the 'in' keyword redundant?


May 25, 2004
Andy Friesen wrote:

> imr1984 wrote:
> Are there any arguments for passing structs by value?

It is be faster for small structs. But I guess, if you want to go for speed, you would use inlining anyway, in which case it does not really matter. It just has to be clear what the semantics are, no matter what the compiler does to achive it.

Furthermore, it has to be clear how other languages are interfaced. If you want to interface a C function that takes a struct as value on the stack, you have to be able to specify that interface in D.

May 25, 2004
Norbert Nemec wrote:

> Andy Friesen wrote:
> 
> 
>>imr1984 wrote:
>>Are there any arguments for passing structs by value?
> 
> 
> It is be faster for small structs. But I guess, if you want to go for speed,
> you would use inlining anyway, in which case it does not really matter. It
> just has to be clear what the semantics are, no matter what the compiler
> does to achive it.

Why is it faster?  And how small is small?

> Furthermore, it has to be clear how other languages are interfaced. If you
> want to interface a C function that takes a struct as value on the stack,
> you have to be able to specify that interface in D.

extern(C/Windows/Pascal) mustn't do this; it defeats their entire reason to exist.  I'm suggesting behaviour for extern(D) only.

 -- andy
May 25, 2004
Andy Friesen wrote:

> Norbert Nemec wrote:
> 
>> Andy Friesen wrote:
>> 
>> 
>>>imr1984 wrote:
>>>Are there any arguments for passing structs by value?
>> 
>> 
>> It is be faster for small structs. But I guess, if you want to go for speed, you would use inlining anyway, in which case it does not really matter. It just has to be clear what the semantics are, no matter what the compiler does to achive it.
> 
> Why is it faster?  And how small is small?

Good question. If the struct is no bigger than one pointer, it is clear that it is faster since you simply save one step of dereferencing. If it is slightly bigger, dereferencing may still be more expensive than copying. Hard to tll.

>> Furthermore, it has to be clear how other languages are interfaced. If you want to interface a C function that takes a struct as value on the stack, you have to be able to specify that interface in D.
> 
> extern(C/Windows/Pascal) mustn't do this; it defeats their entire reason
> to exist.  I'm suggesting behaviour for extern(D) only.

Maybe extern(C/Windows/Pascal/...) should not use the in/inout/out modifiers at all but offer a completely separate set of modifiers fit for each case?