On Wednesday, 19 October 2016 at 19:19:35 UTC, Jonathan M Davis wrote:
That's an orthogonal issue. My point is that normally, a parameter is a ref parameter, because the function is going to use that value and potentially mutate it in the process, and you want the original variable that was passed in to be mutated rather than for the function to be operating on a copy. However, once you can pass rvalues to ref parameters, there will likely be a sharp increase in the number of ref parameters whose entire purpose in being ref is to avoid a copy rather than because the original variable is supposed to be mutated. That increases the risk of accidentally mutating function arguments as well as making it far less obvious when a function is supposed to be mutating its argument. C++ solved that problem by making it so that only const ref parameters could take rvalues, whereas we would be totally open to it if non-const ref parameters accepted rvalues.

Whether the argument escapes the function doesn't matter for any of that. There may be good reasons why you don't want it to, in which case, if scope is implemented to prevent ref parameters from escaping, scope will give you that. But just because you want to mutate the ref argument doesn't necessarily mean that you care about it escaping. You _do_ care if the purpose is simply to avoid a copy, because you don't want the rvalue to escape, since that would be an @safety issue, and so it would make sense to require scope in that case, but at best, that means that the lack of scope indicates that the ref argument is supposed to be mutated as opposed to simply avoid a copy, whereas scope ref says nothing about whether the ref argument is supposed to be mutated or simply avoid a copy - just that whatever the argument is, it should no escape.

Ok, I understand what you mean, but as long as the argument cannot escape I have a different opinion.

So, arguably, it makes more sense to have a new attribute that makes it specifically so that a ref accepts rvalues (e.g. @rvalue ref) rather than making ref in general accept rvalues (the new attribute could even imply scope, since it would be required), but that would mean adding yet another attribute, and we arguably have too many of those already.

- Jonathan M Davis

Yes, we have way to many. So it would make more sense if we add helper/wrappers into phobos (at least for the time being) and refer to them. My byRef "hack" or even my last experiment below could lower the dissatisfaction.

----
struct Vector2f
{
    float x, y;
}

void one(ref const Vector2f v)
{
    writeln(v.x, '|', v.y);
}

void two(ref const Vector2f source, ref const Vector2f target)
{
writefln("From (%.2f|%.2f) to (%.2f|%.2f)", source.x, source.y, target.x, target.y);
}

void invoke(alias f, V...)(V vs)
{
        f(vs);
}

void invoke(F, V...)(F f, V vs)
{
        f(vs);
}

invoke!one(Vector2f(10, 20));
invoke!two(Vector2f(1, 2), Vector2f(3, 4));
        
invoke(&one, Vector2f(10, 20));
invoke(&two, Vector2f(1, 2), Vector2f(3, 4));
----

Reply via email to