July 20, 2018
On Friday, 20 July 2018 at 13:21:11 UTC, Jonathan M Davis wrote:
> On Friday, July 20, 2018 05:16:53 Mike Parker via Digitalmars-d wrote:
>> ...
>
> ...
> Allowing ref to accept rvalues goes completely against the idea that ref is for passing an object so that it can be mutated and have its result affect the caller. With this DIP, we'd likely start seeing folks using ref all over the place even when it has nothing to do with having the function mutating its arguments, and that's not only error-prone, but it obfuscates what ref was originally intended for.
> ...
>

So, if `immutable` would be the default in D, you would be okay with "DIP 1016"?  Because then people would have to write `ref mutable` for mutation
July 20, 2018
On Friday, 20 July 2018 at 09:24:19 UTC, Bastiaan Veelo wrote:
> On Friday, 20 July 2018 at 09:03:18 UTC, Dukc wrote:
>> Thanks for the effort to make it... I believe Manu will be pleased.
>
> Manu is the one who wrote the DIP :-)

Though it was Mike :-)
July 20, 2018
On Friday, July 20, 2018 15:50:29 meppl via Digitalmars-d wrote:
> On Friday, 20 July 2018 at 13:21:11 UTC, Jonathan M Davis wrote:
> > On Friday, July 20, 2018 05:16:53 Mike Parker via Digitalmars-d
> >
> > wrote:
> >> ...
> >
> > ...
> > Allowing ref to accept rvalues goes completely against the idea
> > that ref is for passing an object so that it can be mutated and
> > have its result affect the caller. With this DIP, we'd likely
> > start seeing folks using ref all over the place even when it
> > has nothing to do with having the function mutating its
> > arguments, and that's not only error-prone, but it obfuscates
> > what ref was originally intended for.
> > ...
>
> So, if `immutable` would be the default in D, you would be okay with "DIP 1016"?  Because then people would have to write `ref mutable` for mutation

No. I don't see why that would help at all.

Honestly, if D had immutable by default, I'd probably quit D, because it would make the language hell to use. Some things make sense as immutable but most don't. If I wanted that kind of strait jacket, I'd use a language like Haskell.

But regardless, even if I could put up with a such a default, it wouldn't help, because the use case that Manu is trying to solve would be using ref mutable just like the use cases that ref is normally used for now. There needs to be a distinction between the case where ref is used because the intent is to mutate the object and the case where the intent is to avoid having to copy lvalues and mutation is acceptable but not the goal. C++ solves this by using const, since once const is used, mutation is no longer an issue, so the refness is clearly to avoid copying, but with how restrictive const is in D, it probably wouldn't solve much, because many use cases couldn't use const. We really do need a mutable equivalent to C++'s const&. But Manu's solution unnecesarily destroys the dinstinction between ref being used as means to mutate the argument and ref being used to avoid copying the argument. Since we can't use const for that, we really need a new attribute.

- Jonathan M Davis

July 20, 2018
On Friday, 20 July 2018 at 09:39:47 UTC, Nicholas Wilson wrote:
>> appending something (like .byRef or byRef!long, the latter making an implicit type conversion)
>
> That can't work: either it returns an expired stack temporary (*very* bad), or allocates with no way to deallocate (bad).

How so? It could be made it act exactly as if the temporary was made just before the function call, meaning the lifetime would end at the end of current scope.

Of course, this required compiler magic. A library solution would have exactly the limits you said.

July 20, 2018
On Friday, 20 July 2018 at 13:21:11 UTC, Jonathan M Davis wrote:
> On Friday, July 20, 2018 05:16:53 Mike Parker via Digitalmars-d wrote:
>> [...]
>
> I am completely against allowing ref to accept rvalues without some sort of attribute indicating that it should be allowed to (e.g. @rvalue ref). Allowing ref to accept rvalues goes completely against the idea that ref is for passing an object so that it can be mutated and have its result affect the caller. With this DIP, we'd likely start seeing folks using ref all over the place even when it has nothing to do with having the function mutating its arguments, and that's not only error-prone, but it obfuscates what ref was originally intended for.
>
> [...]

I kinda agree with this, just not so strongly I think.

But as for a UDA, maybe @implicit from the copy constructor DIP can be reused here?

void f(@implicit ref A a) {}

On a side note, I'm not familiar with the talks that've gone around the keyword "in", and I see there's a deprecation issue on bugzilla [1]. Can "in" be added here? "in ref" or just repurposed completely?

Cheers,
- Ali

[1] https://issues.dlang.org/show_bug.cgi?id=18604
July 20, 2018
On Friday, July 20, 2018 16:42:54 aliak via Digitalmars-d wrote:
> On Friday, 20 July 2018 at 13:21:11 UTC, Jonathan M Davis wrote:
> > On Friday, July 20, 2018 05:16:53 Mike Parker via Digitalmars-d
> >
> > wrote:
> >> [...]
> >
> > I am completely against allowing ref to accept rvalues without some sort of attribute indicating that it should be allowed to (e.g. @rvalue ref). Allowing ref to accept rvalues goes completely against the idea that ref is for passing an object so that it can be mutated and have its result affect the caller. With this DIP, we'd likely start seeing folks using ref all over the place even when it has nothing to do with having the function mutating its arguments, and that's not only error-prone, but it obfuscates what ref was originally intended for.
> >
> > [...]
>
> I kinda agree with this, just not so strongly I think.
>
> But as for a UDA, maybe @implicit from the copy constructor DIP can be reused here?
>
> void f(@implicit ref A a) {}

I don't know. Maybe. I'd certainly prefer @rvalue, since it would be clearer (and slightly shorter for that matter), and I don't really agree with copy constructors requiring @implicit anyway. But at the moment, I don't see a technical reason why the attribute couldn't be reused.

> On a side note, I'm not familiar with the talks that've gone around the keyword "in", and I see there's a deprecation issue on bugzilla [1]. Can "in" be added here? "in ref" or just repurposed completely?

in was originally supposed to be const scope, but it's really only ever been const (except for with delegates), since scope hasn't ever done anything for anything other than delegates, and it was never really defined what scope was supposed to do exactly - just the general idea that it was supposed to prevent escaping, not what that really meant in practice or what exactly it didn't allow to escape. DIP 1000 actually defines what scope does in detail and makes it work for far more than delegates. However, if in were then to actually mean const scope as originally intended, then a large percentage of code would break if it used -dip1000 (and would of course break once -dip1000 becomes the default), so in has officially become just const. However, some folks are quite unhappy about that, and -dip1000 breaks tons of stuff anyway, so arguably, we should just allow in to mean const scope and have it break whatever it breaks. So, what's actually going to happen with that is unclear - especially since we really don't have a clean migration path to making -dip1000 the default anyway, But for now, in just means const.

Regardless, in has never had anything to do with ref. So, making it imply ref now would definitely break code, and since in has always implied const, if we were talking about using in for any of this, we might as well just go with const ref like C++ does, though given how restrictive D's const is, that's arguably a very poor solution.

- Jonathan M Davis

July 20, 2018
On Fri, 20 Jul 2018 at 02:05, Dukc via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Friday, 20 July 2018 at 05:16:53 UTC, Mike Parker wrote:
> > This is the feedback thread for the first round of Community Review for DIP 1016, "ref T accepts r-values"
>
> I'd prefer a solution which allows one to make an invisible temp manually without making a new statement or a new symbol name. By appending something (like .byRef or byRef!long, the latter making an implicit type conversion) after a rvalue statement. This would still prevent things like byRefFunction(aVariable.incremented) when incremented copies the value without the user excepting it.

This undermines one of the core reasons for the DIP; you're just substituting one awkward edge case with a different awkward edge case. Meta code is much simpler and less error-prone when there aren't syntactic edge cases associated with interacting with ref args, and as soon as they exist, library authors write some template without such explicit support for reference args (perhaps they never thought of it), and the end-user experiences nasty surprises.

> But If the options are either your solution or the present situation, yours is still better. Thanks for the effort to make it... I believe Manu will be pleased.

I'll be pleased if it doesn't get rejected on principle ;)
July 20, 2018
On Fri, 20 Jul 2018 at 02:25, Bastiaan Veelo via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Friday, 20 July 2018 at 05:16:53 UTC, Mike Parker wrote:
> > This is the feedback thread for the first round of Community Review for DIP 1016, "ref T accepts r-values":
> >
> > https://github.com/dlang/DIPs/blob/725541d69149bc85a9492f7df07360f8e2948bd7/DIPs/DIP1016.md
>
> The only difficulty I had was reading
> > An example may be some meta that reflects or receives a function by alias.
> My difficulties are with the word “meta” used as a noun and what “reflecting a function” means. I think I would have worded it as
> > An example may be some template with an ‘alias’ parameter that is instantiated on a function.

I use the term 'meta' because it's not so clear how the construction
emerges; it is often not a single template, because that's relatively
easy to control, but rather some construction or composition with
components from 3rd party libs which you don't control. (I've made
that point elsewhere)
I use 'meta' to generally refer to any such machinery in any form.

July 20, 2018
On Friday, 20 July 2018 at 17:02:04 UTC, Jonathan M Davis wrote:
> On Friday, July 20, 2018 16:42:54 aliak via Digitalmars-d wrote:
>> On Friday, 20 July 2018 at 13:21:11 UTC, Jonathan M Davis
>>
>> But as for a UDA, maybe @implicit from the copy constructor DIP can be reused here?
>>
>> void f(@implicit ref A a) {}
>
> I don't know. Maybe. I'd certainly prefer @rvalue, since it would be clearer (and slightly shorter for that matter), and I don't really agree with copy constructors requiring @implicit anyway. But at the moment, I don't see a technical reason why the attribute couldn't be reused.
>

I find the DIP addresses this in a cleaner way with opt-out.
1) Avoids adding more UDA:s
2) It's probably more common to wish to use this feature than the opposite, i.e. by taking the opt-out route we can significantly reduce @uda clutter.

See DIP:
> void lval_only(int x) @disable;
> void lval_only(ref int x);
>
> int x = 10;
> lval_only(x);  // ok: choose by-ref
> lval_only(10); // error: literal matches by-val, which is @disabled


July 20, 2018
On Fri, 20 Jul 2018 at 03:10, Dgame via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Friday, 20 July 2018 at 09:39:47 UTC, Nicholas Wilson wrote:
> > On Friday, 20 July 2018 at 09:03:18 UTC, Dukc wrote:
> >> appending something (like .byRef or byRef!long, the latter
> >> making an implicit type conversion)
> >
> > That can't work: either it returns an expired stack temporary
> > (*very* bad), or allocates with no way to deallocate (bad).
>
> What about something like this?
>
> ----
> import std.stdio;
>
> ref T byRef(T)(T value) {
>      static T _val = void;
>      _val = value;
>
>      return _val;
> }
>
> void foo(ref int a) {
>      writeln("A = ", a);
> }
>
> void main() {
>      foo(42.byRef);
>      foo(23.byRef);
> }
> ----

Substitutes one class of edge case with a different style of edge case. This general approach doesn't solve my biggest bugbear.