ref arguments

Jeremie Pelletier jeremiep at gmail.com
Mon Sep 21 12:53:31 PDT 2009


Steven Schveighoffer wrote:
> On Mon, 21 Sep 2009 14:28:09 -0400, Jeremie Pelletier 
> <jeremiep at gmail.com> wrote:
> 
>> Steven Schveighoffer wrote:
>>> On Mon, 21 Sep 2009 12:23:46 -0400, Jeremie Pelletier 
>>> <jeremiep at gmail.com> wrote:
>>>>
>>>> 'in' means 'const scope' in D2, which is using pass-by-value semantics.
>>>  Yes, you are right.  I can't see the benefit to it, so I guess my 
>>> recommendation is not to ever use in (use const instead).
>>
>> I disagree, I have different uses for both. I use 'in' when the 
>> reference will not leave the function's scope and const when it does. 
>> Both are immutable views on the data but with different usage 
>> semantics. The different semantics aren't yet implemented in D2 but 
>> they are most useful to determine whether I can, for example, decide 
>> whether to send a slice (to in parameters) or a copy (to const 
>> parameters).
> 
> Yes, that would be useful if it was enforced.  But it's not, so it's not 
> useful.  Unless you trust the compiler in your head :)

It's useful when I look back at the prototype to get an idea of how I 
used the parameter without looking at the entire function body. Besides 
if it ever gets enforced my code will be ready, its just good practice 
in my book.

>>>> I myself stay out of 'ref' and 'out' params since they do not yet 
>>>> optimize and add quite a lot of overhead making temporary "safe" 
>>>> copies of the data.
>>>  I understand the problem behind not optimizing  (inline), but I'm 
>>> not sure what you mean by making temporary "safe" copies.
>>
>> Right now the compiler makes a temporary copy of referenced parameters 
>> on the stack, calls the function with a pointer to the stack copy, and 
>> once the function returns copies the modified temporary back to its 
>> original location. This is quite considerable overhead.
> 
> Are you sure this is true?  I don't have a d2 compiler right now, but 
> that sounds like a *huge* step in the wrong direction.  D1 does not do 
> this (tested dmd 1.046).

Yeah I started a thread about that a few months ago in digitalmars.D, 
its something that's on the bugzilla I believe.

>>
>>>> Also 'scope' params have a meaning, when a delegate parameter is 
>>>> declared as scope, it allows a closure to use stack storage instead 
>>>> of the usual heap storage.
>>>  yes, but in the context of an 'in' parameter, most of the time you 
>>> are not passing a delegate using in, so scope doesn't mean much there.
>>
>> The implied 'scope' in 'in' has no effect yet due to a current 
>> compiler bug. You have to explicitly use 'scope' when declaring 
>> delegate parameters. Just like the 'in' vs 'const' have different 
>> semantics, 'in' vs plain 'scope' also have different semantics, which 
>> should get fixed soon.
> 
> Yes, I understand the reasoning for scope delegates.  My point was that
> 1. scope for non-delegate parameters is currently a noop
> 2. const does not make any sense for a delegate.
> 
> So arguing that the 'scope' part of 'in' is useful for delegates is 
> currently a moot point.  I guess you could use it as a quicker way to 
> type scope or const, but it currently doesn't have any different use 
> than just typing 'scope' (for delegates) or 'const' (for other types).

There again, its just good practice to know what the keywords implies 
when using them even if they are noops, you never know when that noop 
turns into enforcement. Although I agree that const delegates and scope 
values doesn't mean anything. I myself only use 'in' on references, 
values gets 'const'.

>>
>> For example, consider the following:
>>
>> void Foo(scope delegate() bar) { bar(); }
>> void Foo2(delegate() bar) { bar(); }
>>
>> // This method uses stack storage, the implied scope in 'in' should 
>> also work here, but is bugged right now so explicit 'scope' is needed
>> void Test() {
>>      void Bar() {}
>>      Foo(&Bar);
>> }
>>
>> // This method uses heap storage allocated on the GC through 
>> _d_allocmemory
>> // Notice how the only difference is the 'scope' qualifier of Foo2()
>> void Test2() {
>>      void Bar() {}
>>      Foo2(&Bar);
>> }
> 
> it's still incomplete.  For example, this still allocates a closure on 
> the heap:
> 
> void Bar() {}
> auto x = &Bar;
> Foo2(x);
> 
> I think scope will have to become a type-modifier before it is a 
> complete solution.

Yeah, that is also a current bug in bugzilla, local pointers to local 
closures should not trigger heap allocations.


More information about the Digitalmars-d-learn mailing list