April 11, 2013
2013/4/11 Dicebot <m.strashun@gmail.com>

> You don't think exposing creation of temporaries is low level
> implementation
> detail?
>

No. In this case, it is the purpose of 'scope ref', not is the implementation details.

What is the language semantics and what is the implementation detail - that varies depending on what is properly supported in the language. D explicitly distinguishes lvalues and rvalues, and also defines that rvalue cannot be taken its address (== reference).

The purpose of 'scope ref' is that the parameter can be received both lvalues and rvalues with one function body. To receive lvalues, scope ref should take the address of them. As a conclusion, to receive rvalues temporary creation is necessary in caller site.

Yes, it mostly represents implementation details, but it is still
description of language semantics.
This confusion is almost inevitable. Because the essential purpose of
'scope ref' is already "efficiency".

Furthermore, note that the desired "efficiency" is not "the speed of
argument passing".
I recognize that it is "to avoid code bloating of function body". If you
need "most efficient argument passing", you should choose it from the
argument type. 'scope ref' is not a thing to make the choice automatic.

Kenji Hara


April 11, 2013
Isn's it too strict? The following example would not work because you cannot take the address of the parameter. But it would still be nice to have it passed by ref and scoped:

struct Item
{
   int data;
   Item* next;
}

void printThem(const scope ref Item first)
{
    auto it = &first;
    while (it)
    {
        std.stdio.writeln(*it);
        it = it.next;
    }
}


/Jonas
April 11, 2013
On Thursday, 11 April 2013 at 09:27:11 UTC, kenji hara wrote:
> No. In this case, it is the purpose of 'scope ref', not is the
> implementation details.
>
> What is the language semantics and what is the implementation detail - that
> varies depending on what is properly supported in the language. D
> explicitly distinguishes lvalues and rvalues, and also defines that rvalue
> cannot be taken its address (== reference).
>
> The purpose of 'scope ref' is that the parameter can be received both
> lvalues and rvalues with one function body. To receive lvalues, scope ref
> should take the address of them. As a conclusion, to receive rvalues
> temporary creation is necessary in caller site.
>
> Yes, it mostly represents implementation details, but it is still
> description of language semantics.
> This confusion is almost inevitable. Because the essential purpose of
> 'scope ref' is already "efficiency".
>
> Furthermore, note that the desired "efficiency" is not "the speed of
> argument passing".
> I recognize that it is "to avoid code bloating of function body". If you
> need "most efficient argument passing", you should choose it from the
> argument type. 'scope ref' is not a thing to make the choice automatic.
>
> Kenji Hara

I trust your judgement then, will update DIP then. But I am still afraid of confusion.
April 12, 2013
On Wednesday, 10 April 2013 at 07:43:57 UTC, Dicebot wrote:
> Consistent behavior is important but it does not change the fact that there two types of rvalues in the language - raw literals (42, A.init) and constructed temporaries (A()). Accepting rvalues of the first type in as mutable references may be consistent from the point of view of syntax by _extremely_ confusing semantics-wise:
>
> void foo(scope ref int x)
> {
>     x = 32;
> }
>
> void main()
> {
>     foo(42); // erm, 32 is the new 42 or ref is not actually ref?
> }
>
> Beauty of "in ref" is that in that case user can't use it in any way that may disclose the fact the temporary variable for non-adressable entities is created. For mutable scope ref it is not the case and we must leak implementation details, which is never good.
>
> Another concern is that if someone tries to pass "42" as a mutable ref, most likely he does not really wants it to be mutable and "in ref" is a better match.
>
> This may not be consistent from the point of view of generic code, but it is now consistent from the point of view of programmer : A(...) construct always create temporaries, raw value literals never do (well, they will for "in ref" but you can't observe it). I think this is much more important.
>
> One extra thing to note is that test32 may actually work if it instantiates T as "const int" for 42 (making it "in ref" essentially), but I don't know if D rules allow it.

I think this is another case of two different features which may or may not be paired up together. If it is always okay to have A accompany B, and B accompany A, it's good from a syntax point of view because you only need one syntax for both of them. But if you pair them up and later think, I wish I could do A without having to do B, or B without having to do A, then you'll regret pairing them up because you'll either have to break code or live with what you've got.

When you say we shouldn't be able to return an rvalue temporaries, even if they're safe, I think it's reasonable, not a life or death issue. But if 'scope ref' is used to mean that, you're also saying that any *other* feature which wants 'scope', such as 'ref' safety (why I created DIP35, to highlight this), will automatically also have to take rvalue temps because they're bound up with it, it's more risky.

Some of these will be a judgment call - A and B  are sometimes so similar that it's better to save on syntax than differentiate them. 'const scope' might be the same way.
April 12, 2013
Kenji, what do you think, should we / you create a pull request for the proposal?
Most seem to be very satisfied with the proposal. In addition, a pull request would rather cause that Walter and Andrei join the discussion.
April 17, 2013
Thanks to Kenji there is now a corresponding pull request:
https://github.com/D-Programming-Language/dmd/pull/1903

Let us hope that it will be quickly merged.

I still hope that Andrei or Walter say something to this topic.
Maybe we have a chance with this pull request. ;)
April 17, 2013
On Wednesday, 17 April 2013 at 17:50:07 UTC, Namespace wrote:
> Thanks to Kenji there is now a corresponding pull request:
> https://github.com/D-Programming-Language/dmd/pull/1903
>
> Let us hope that it will be quickly merged.
>
> I still hope that Andrei or Walter say something to this topic.
> Maybe we have a chance with this pull request. ;)

Finally, I'm tired of copy-pasting the same code just to change to "ref". :)
April 17, 2013
> Finally, I'm tired of copy-pasting the same code just to change to "ref". :)

What do you mean?
April 17, 2013
On Wednesday, 17 April 2013 at 19:29:51 UTC, Namespace wrote:
>> Finally, I'm tired of copy-pasting the same code just to change to "ref". :)
>
> What do you mean?

This:

/// dot product of two Vector3 vectors
auto dot(T) (Vector3!T u, Vector3!T v) @safe pure nothrow
{
	return u.x * v.x + u.y * v.y + u.z * v.z;
}

/// dot product of two Vector3 vectors
auto dot(T) (ref Vector3!T u, ref Vector3!T v) @safe pure nothrow
{
	return u.x * v.x + u.y * v.y + u.z * v.z;
}
April 17, 2013
On Wednesday, 17 April 2013 at 20:18:56 UTC, Minas Mina wrote:
> On Wednesday, 17 April 2013 at 19:29:51 UTC, Namespace wrote:
>>> Finally, I'm tired of copy-pasting the same code just to change to "ref". :)
>>
>> What do you mean?
>
> This:
>
> /// dot product of two Vector3 vectors
> auto dot(T) (Vector3!T u, Vector3!T v) @safe pure nothrow
> {
> 	return u.x * v.x + u.y * v.y + u.z * v.z;
> }
>
> /// dot product of two Vector3 vectors
> auto dot(T) (ref Vector3!T u, ref Vector3!T v) @safe pure nothrow
> {
> 	return u.x * v.x + u.y * v.y + u.z * v.z;
> }

Oh, I thought you had anything against the DIP. ^^
Yes that annoys me as well. That's why I really hope that we can fix this vexing issue soon. :)