Thread overview
in / out for C++ programmers
Mar 24, 2012
Dan
Mar 24, 2012
Jonathan M Davis
Mar 24, 2012
Ali Çehreli
Mar 24, 2012
Jonathan M Davis
Mar 24, 2012
Ali Çehreli
Mar 24, 2012
Jonathan M Davis
Mar 24, 2012
Jonathan M Davis
Mar 24, 2012
Ali Çehreli
Mar 24, 2012
Ali Çehreli
March 24, 2012
When would you use in / out parameters instead of ref & const keywords?

Thanks.
March 24, 2012
On Saturday, March 24, 2012 07:28:08 Dan wrote:
> When would you use in / out parameters instead of ref & const keywords?

out sets the variable to its init value, so you don't run into issues with the behavior of the function changing based on the value of the variable that you passed in. out is intended for variables that are for returning an extra value from the function, not passing one in. You use ref if you want to actually use the value that you pass in.

in is the same as const scope and has nothing to do with ref at all.

- Jonathan M Davis
March 24, 2012
On 03/23/2012 11:28 PM, Dan wrote:
> When would you use in / out parameters instead of ref & const keywords?

I am just about finished translating a chapter exactly on that topic. I've just realized that I have some questions myself. :)

'out' is the equivalent of a reference in C++, with additionally initializing the out parameter upon entry to the function.

void foo(out int i)
{
    assert(i == 0);  // regardless of what it was before the call
}

'in' is the same as 'const scope'. const part is easy to understand but I don't know what 'scope' does. I could not understand what the spec means with "references in the parameter cannot be escaped (e.g. assigned to a global variable)" for scope:

  http://dlang.org/function.html

'ref' is the same as a C++ reference.

Ali

March 24, 2012
On Friday, March 23, 2012 23:37:27 Ali Çehreli wrote:
> 'in' is the same as 'const scope'. const part is easy to understand but I don't know what 'scope' does. I could not understand what the spec means with "references in the parameter cannot be escaped (e.g. assigned to a global variable)" for scope:
> 
>    http://dlang.org/function.html

You mean that you don't understand what it means for a reference to escape a function? One example of this with pointers would be

int* func()
{
    int a;
    return &a;
}

A pointer to a local variable has escaped the function. That pointer is invalid. A case this simple gets caught by the compiler, but it's very easy to get around that (e.g. passing &a to a function which returns it and then return the result of that function rather than &a directly).

In the case of scope, it means that what you pass in cannot be assigned to a global or static variable, and it cannot be returned from that function. So, for instance.

int[] foo(const int[] a)
{
    ...
}

could not assign a to a global or static variable and cannot return it. This can allow some additional optimizations as well as improve safety in some cases. For instance, if you pass

int[5] b;

to foo, then you know that no slice of that static array will escape, since something like

int[] bar()
{
    int[5] c;
    return c;
}

is just as bad as the case with &a. I believe that scope is used primarily with delegates however (particularly, since you often _want_ to be able to return a slice of an array passed to a function). It guarantees that the the delegate's context won't escape the function and can make it so that the delegate's context doesn't have to be allocated on the heap, which improves efficiency.

scope is pointless with types which aren't pointers or references though.

- Jonathan M Davis
March 24, 2012
On 03/23/2012 11:50 PM, Jonathan M Davis wrote:
> On Friday, March 23, 2012 23:37:27 Ali Çehreli wrote:
>> 'in' is the same as 'const scope'. const part is easy to understand but
>> I don't know what 'scope' does. I could not understand what the spec
>> means with "references in the parameter cannot be escaped (e.g. assigned
>> to a global variable)" for scope:
>>
>>     http://dlang.org/function.html
>
> You mean that you don't understand what it means for a reference to escape a
> function?

No. I've known that for decades now. I don't understand it because I've tried what I've understood about scope in code examples and could not see any difference.

Also, I don't understand the semantics of it. For example, 'const' is welcoming: it says "I accept mutable and immutable references as parameters." (Because it is a guarantee that it will not modify.) 'immutable' is restricting: "I accept only immutable references."

What is 'scope' on a parameter? Is that a guarantee or a requirement on the argument?

> In the case of scope, it means that what you pass in cannot be assigned to a
> global or static variable, and it cannot be returned from that function. So,
> for instance.
>
> int[] foo(const int[] a)
> {
>      ...
> }
>
> could not assign a to a global or static variable and cannot return it.

Yet this compiles:

int[] g;

int[] foo(scope int[] slice)
{
    g = slice;
    return slice;
}

void main()
{
    int[] slice;
    int[] result = foo(slice);
}

The funny thing is, what does function have to do the scope of a parameter that is passed to it? Since it's an argument passed from the outside it may be scoped or dynamic.

And that's why I don't understand it. :) I suspect scope is a remnant from the D1 days. (?)

> This
> can allow some additional optimizations as well as improve safety in some
> cases. For instance, if you pass
>
> int[5] b;
>
> to foo, then you know that no slice of that static array will escape, since
> something like
>
> int[] bar()
> {
>      int[5] c;
>      return c;
> }
>
> is just as bad as the case with&a. I believe that scope is used primarily
> with delegates however (particularly, since you often _want_ to be able to
> return a slice of an array passed to a function).

Fine, delegates... Is that a guarantee or a requirement in that context?

> It guarantees that the the
> delegate's context won't escape the function and can make it so that the
> delegate's context doesn't have to be allocated on the heap, which improves
> efficiency.
>
> scope is pointless with types which aren't pointers or references though.
>
> - Jonathan M Davis

Ali

March 24, 2012
On Saturday, March 24, 2012 00:02:58 Ali Çehreli wrote:
> On 03/23/2012 11:50 PM, Jonathan M Davis wrote:
>  > On Friday, March 23, 2012 23:37:27 Ali Çehreli wrote:
>  >> 'in' is the same as 'const scope'. const part is easy to understand
>  >> but
>  >> I don't know what 'scope' does. I could not understand what the spec
>  >> means with "references in the parameter cannot be escaped (e.g.
>  >> assigned
>  >>
>  >> to a global variable)" for scope:
>  >>     http://dlang.org/function.html
>  >
>  > You mean that you don't understand what it means for a reference to
> 
> escape a
> 
>  > function?
> 
> No. I've known that for decades now. I don't understand it because I've tried what I've understood about scope in code examples and could not see any difference.
> 
> Also, I don't understand the semantics of it. For example, 'const' is welcoming: it says "I accept mutable and immutable references as parameters." (Because it is a guarantee that it will not modify.) 'immutable' is restricting: "I accept only immutable references."
> 
> What is 'scope' on a parameter? Is that a guarantee or a requirement on the argument?
> 
>  > In the case of scope, it means that what you pass in cannot be
> 
> assigned to a
> 
>  > global or static variable, and it cannot be returned from that
> 
> function. So,
> 
>  > for instance.
>  >
>  > int[] foo(const int[] a)
>  > {
>  >
>  >      ...
>  >
>  > }
>  >
>  > could not assign a to a global or static variable and cannot return it.
> 
> Yet this compiles:
> 
> int[] g;
> 
> int[] foo(scope int[] slice)
> {
>      g = slice;
>      return slice;
> }
> 
> void main()
> {
>      int[] slice;
>      int[] result = foo(slice);
> }
> 
> The funny thing is, what does function have to do the scope of a parameter that is passed to it? Since it's an argument passed from the outside it may be scoped or dynamic.
> 
> And that's why I don't understand it. :) I suspect scope is a remnant
> from the D1 days. (?)

The point of scope is to guarantee that no references to the argument passed in can escape the function. The variable passed in is irrelevant aside from whether it's a reference type (or pointer) or not. Now, there's every possibility (guarantee even, given your example) that scope is buggy. But as I understand it (and the spec seems to agree), the whole point of scope is to make it illegal for any argument passed to that parameter to escape the function it's being passed to. So, it restricts what the callee can do, but it doesn't restrict the caller.

>  > This
>  > can allow some additional optimizations as well as improve safety in
>  > some
>  > cases. For instance, if you pass
>  >
>  > int[5] b;
>  >
>  > to foo, then you know that no slice of that static array will escape,
> 
> since
> 
>  > something like
>  >
>  > int[] bar()
>  > {
>  >
>  >      int[5] c;
>  >      return c;
>  >
>  > }
>  >
>  > is just as bad as the case with&a. I believe that scope is used
>  > primarily
>  > with delegates however (particularly, since you often _want_ to be
> 
> able to
> 
>  > return a slice of an array passed to a function).
> 
> Fine, delegates... Is that a guarantee or a requirement in that context?

If the parameter that a delaget is being passed to is marked as scope, then it's supposed to be illegal for any references to it or its context to escape the function it's being passed to, which makes it possible for the compiler to avoid putting the delegate's context on the heap. That is a guarantee, and if it's not true, then the compiler is buggy. What I don't know is if the language guarantees that the compiler will do the optimization of not putting the delegate's context on the heap if it's passed to a scope parameter.

- Jonathan M Davis
March 24, 2012
On 03/23/2012 11:50 PM, Jonathan M Davis wrote:
> I believe that scope is used primarily
> with delegates however (particularly, since you often _want_ to be able to
> return a slice of an array passed to a function). It guarantees that the the
> delegate's context won't escape the function and can make it so that the
> delegate's context doesn't have to be allocated on the heap, which improves
> efficiency.

Ok, I read it more carefully. What you are saying is that 'scope' may make more sense when applied to a parameter of a delegate.

There are two parties involved:

- User of the delegate as in dlg(someArg);

- Creater of the delegate as in 'return a => a + localVariable;'

Is that a requirement of the delegate or the user of the delegate in that case? Or, is that a guarantee of the delegate or the caller of the delegate?

Yes, I am completely lost on the semantics of 'scope' parameters. :)

Ali

March 24, 2012
Apparently, scope parameters aren't currently checked at all, so they're _very_ buggy:

http://d.puremagic.com/issues/show_bug.cgi?id=6931

- Jonathan M Davis
March 24, 2012
On 03/24/2012 12:18 AM, Jonathan M Davis wrote:
> Apparently, scope parameters aren't currently checked at all, so they're
> _very_ buggy:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=6931
>
> - Jonathan M Davis

Thank you. I take it that 'scope' is a way of a function to promise that it will not hold on to that reference longer than the function call. In this sense, 'scope' means "the caller may pass in variables of *even* scope duration."

That makes sense to me. :)

Ali