May 10, 2013
On Thu, 09 May 2013 22:10:22 -0400, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Thursday, May 09, 2013 21:56:53 Steven Schveighoffer wrote:
>> What about specifying ref at the call site when you know you want the data
>> modified?
>>
>> fix(ref c[i]);
>>
>> Then if c decides to start returning by value, this is a compiler error.
>>
>> IMO, fix really should take a pointer. But we want to avoid pointers due
>> to the danger of them.
>>
>> so this is like applying & but keeps it safe.
>
> That would be great except for UFCS. How would you designate the ref when it's
> the first argument? And I think that it's worse to have ref optional at the
> callsite than to not have it at all.

1. using UFCS is optional.  c[i].fix() works as well as fix(c[i]).
2. We could say UFCS has an implicit ref-at-callsite if needed, and will not compile for rvalues.  If you think about it, 'this' is implicitly ref, and UFCS is calling like the first argument is the 'this' reference.

> If it weren't for UFCS, I probably would be in favor of requiring it at the
> callsite, but I just don't see how that could work with UFCS. Maybe C# has a
> way to deal with that, since it does have some sort of UFCS, and it does
> require ref at the callsite (at least from what I understand - I haven't used
> C# much)?

C# required ref when I used it.  It was actually kind of nice because it was self-documenting.

But I don't think it's something we could add as a requirement, too much code uses ref.

I don't think it is bad to make it optional.  The caller can put restrictions he desires on types just like the callee can.  Consider that the author of fix could change his code to double fix(double), and now the code also is useless.  We can't possibly guard against that, because lvalues also bind to non-ref.

I tend to feel that any modification that adds or removes ref is a severe breaking change, and is so bad that it shouldn't be done without also changing the name of the function anyway.

-Steve
May 10, 2013
On Thu, 09 May 2013 22:14:33 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 5/9/13 10:05 PM, Steven Schveighoffer wrote:
>> On Thu, 09 May 2013 21:47:14 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 5/9/13 4:36 PM, Peter Alexander wrote:
>>>> I'm not sure about how common it is, but I really don't like the idea of
>>>> calls like swap(1, 2) being legal. Seems like a step backward from C++.
>>>
>>> I think if we ever get swap(1, 2) to compile and run we'd effectively
>>> have destroyed the D programming language.
>>
>> Depends on context.
>>
>> int swap(int diskNum, int partitionNum);
>>
>> Someone pointed out that swap could be a function that swaps heap
>> indexes, and might even take by ref not caring if you want the resulting
>> value that was swapped.
>>
>> with(someHeap)
>> {
>> swap(1, 2); // swap indexes 1 and 2
>> }
>>
>> -Steve
>
> Now that's great trolling!

That's not great trolling, it's *clever* trolling ;)

I was actually half serious though, the name of the function is really important here, including the context.

-Steve
May 10, 2013
On 5/9/13 10:23 PM, Dmitry S wrote:
> To clear my name, just in case: I wasn't trolling.

And to clear mine: I was referring to std.swap, which swaps two values.

Andrei
May 10, 2013
On Thursday, May 09, 2013 22:33:09 Steven Schveighoffer wrote:
> On Thu, 09 May 2013 22:10:22 -0400, Jonathan M Davis <jmdavisProg@gmx.com>
> > That would be great except for UFCS. How would you designate the ref
> > when it's
> > the first argument? And I think that it's worse to have ref optional at
> > the
> > callsite than to not have it at all.
> 
> 1. using UFCS is optional.  c[i].fix() works as well as fix(c[i]).

That would be an option, but as I explain belong, I think that having ref be optional at the call site is a bad idea.

> 2. We could say UFCS has an implicit ref-at-callsite if needed, and will not compile for rvalues.  If you think about it, 'this' is implicitly ref, and UFCS is calling like the first argument is the 'this' reference.

That would make using UFCS with ranges generally illegal, as most range-based funtions do not have ref parameters, and you generally don't want them to be passed by ref.

> > If it weren't for UFCS, I probably would be in favor of requiring it at
> > the
> > callsite, but I just don't see how that could work with UFCS. Maybe C#
> > has a
> > way to deal with that, since it does have some sort of UFCS, and it does
> > require ref at the callsite (at least from what I understand - I haven't
> > used
> > C# much)?
> 
> C# required ref when I used it.  It was actually kind of nice because it was self-documenting.
> 
> But I don't think it's something we could add as a requirement, too much code uses ref.
> 
> I don't think it is bad to make it optional.

This has come up on the newsgroup before, and I really do think that having it as optional is worse than not having it. If it's required, then when you see that an argument is marked with ref, you know that the parameter is a ref parameter, and when you see an argument without ref, you know that the parameter is not a ref parameter. And the compiler enforces both, so you always catch it when the function changes.

On the other hand, if ref at the callsite is optional, then the lack of ref at the call site means absolutely nothing. You're still going to have to look at every single function signature to determine if it takes a ref argument or not, meaning that the lack of ref at the call site buys you nothing at best and harms you at worst, because it gives you a false sense of security that the argument is not being passed by ref. Programmers would have to be 100% consistent in using ref at the callsite to avoid that, and that's obviously not going to happen.

You _do_ still get the gain that if you use ref at the call site, then your code will break if the parameter is no longer ref. But I think that the fact that the lack of ref means nothing while still giving the impression that the parameter is not a ref parameter is worse than never having ref at the call site.

- Jonathan M Davis
May 10, 2013
On Friday, 10 May 2013 at 04:44:29 UTC, Jonathan M Davis wrote:
>> 2. We could say UFCS has an implicit ref-at-callsite if needed, and will
>> not compile for rvalues.  If you think about it, 'this' is implicitly ref,
>> and UFCS is calling like the first argument is the 'this' reference.
>
> That would make using UFCS with ranges generally illegal, as most range-based
> funtions do not have ref parameters, and you generally don't want them to be
> passed by ref.
>

Why ? Range behavior is undefined when passed by value.

> On the other hand, if ref at the callsite is optional, then the lack of ref at
> the call site means absolutely nothing. You're still going to have to look at
> every single function signature to determine if it takes a ref argument or
> not, meaning that the lack of ref at the call site buys you nothing at best
> and harms you at worst, because it gives you a false sense of security that
> the argument is not being passed by ref. Programmers would have to be 100%
> consistent in using ref at the callsite to avoid that, and that's obviously
> not going to happen.
>

It make sense when you pass by ref to modify things. In this case passing an rvalue don't make any sense. If you di it for performance, then this is yet another instance of the compiler rewriting things to improve performances.
May 10, 2013
On Friday, May 10, 2013 07:01:21 deadalnix wrote:
> On Friday, 10 May 2013 at 04:44:29 UTC, Jonathan M Davis wrote:
> >> 2. We could say UFCS has an implicit ref-at-callsite if
> >> needed, and will
> >> not compile for rvalues.  If you think about it, 'this' is
> >> implicitly ref,
> >> and UFCS is calling like the first argument is the 'this'
> >> reference.
> > 
> > That would make using UFCS with ranges generally illegal, as
> > most range-based
> > funtions do not have ref parameters, and you generally don't
> > want them to be
> > passed by ref.
> 
> Why ? Range behavior is undefined when passed by value.

In some cases you don't care, but ranges are almost always passed by value, and when you're worried about ranges being reference types, you call save, meaning that if you're chaining, you're even more likely to passing an rvalue. And even if a range is a reference type, it's frequently not an lvalue, because it's frequently the return value of a function, and it's frequently the case that such return values can't be returned by ref, so requiring ref for UFCS would have a tendency to kill function chaining via UFCS.

> > On the other hand, if ref at the callsite is optional, then the
> > lack of ref at
> > the call site means absolutely nothing. You're still going to
> > have to look at
> > every single function signature to determine if it takes a ref
> > argument or
> > not, meaning that the lack of ref at the call site buys you
> > nothing at best
> > and harms you at worst, because it gives you a false sense of
> > security that
> > the argument is not being passed by ref. Programmers would have
> > to be 100%
> > consistent in using ref at the callsite to avoid that, and
> > that's obviously
> > not going to happen.
> 
> It make sense when you pass by ref to modify things. In this case passing an rvalue don't make any sense. If you di it for performance, then this is yet another instance of the compiler rewriting things to improve performances.

The only time that it would make sense to put ref at the callsite is if you intend to mutate the object (and the ref at the callsite is then intended to signal that to the programmer as well as get the compiler to verify that it's being passed by ref). If plain ref were to accept rvalues, then ref at the callsite would be pretty much meaningless. And it would never make sense to use it with something like auto ref.

- Jonathan M Davis
May 10, 2013
On Friday, 10 May 2013 at 05:01:22 UTC, deadalnix wrote:
> Why ? Range behavior is undefined when passed by value.

Ugh, it is usually other way around, at least given current typical range implementations.
May 10, 2013
10-May-2013 04:18, Manu пишет:
> On 10 May 2013 09:20, Rob T <alanb@ucora.com <mailto:alanb@ucora.com>>
> wrote:
>
>     On Thursday, 9 May 2013 at 22:42:14 UTC, Manu wrote:
>
>         And it's
>
>             even questionable that scope as originally intended can be
>             properly
>             implemented anyway.
>
>
>         ...so, the problem is no different than 'auto ref' as you
>         mention above.
>         It's not implemented as drafted, and we're debating what's actually
>         correct. Clearly the draft was incomplete in both cases.
>         I only support the proposal (from others) that scope ref makes
>         so much more
>         sense, and I think we've also proven it can be made to work
>         syntactically
>         without holes, which I don't believe is so for auto ref.
>
>
>     However despite the elusiveness of a solution, it looks like we'll
>     be able to implement auto ref as was originally intended. We may
>     also be able to implement scope as was originally intended, but not
>     if we use it for another purpose.
>
>
> Except that auto ref as originally intended seems to have been a flawed
> design, as evidenced by the massive waves this issue keeps creating.
>

Simply put it wasn't ever implemented like it was meant to.
When something doesn't exist it's hard to believe that its broken.

In fact I expected it to mean what you seem to attribute to scope ref i.e. ~ as C++ const& minus logical const part.
The desire to make 2 versions of function in template case is serving one use case only - perfect forwarding and IMO is hacky. Funnily tough this corner-case beast (for templates) is implemented and the chief usage (for normal functions) isn't.

-- 
Dmitry Olshansky
May 10, 2013
On Friday, 10 May 2013 at 00:08:50 UTC, Manu wrote:
> As I've had to re-iterate countless times, and such is the massive fallacy
> behind all of these threads, this whole debate is NOT about
> lvalues/rvalues, and I wish people would stop using the term 'rvalue' in
> their posts, I worry that they misunderstand the problem every time it's
> said.
>
> This code is broken:
>   void f(ref int x) {}
>   int x;
>   f(x);
>
> x is an lvalue.

There's nothing broken about that code. In what way do you believe it is broken?


> The problem we need to solve is that of a function being able to safely
> receive a _temporary_.

temporary = rvalue

May 10, 2013
On Fri, 10 May 2013 00:44:08 -0400, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Thursday, May 09, 2013 22:33:09 Steven Schveighoffer wrote:
>> On Thu, 09 May 2013 22:10:22 -0400, Jonathan M Davis <jmdavisProg@gmx.com>
>> > That would be great except for UFCS. How would you designate the ref
>> > when it's
>> > the first argument? And I think that it's worse to have ref optional  
>> at
>> > the
>> > callsite than to not have it at all.
>>
>> 1. using UFCS is optional.  c[i].fix() works as well as fix(c[i]).
>
> That would be an option, but as I explain belong, I think that having ref be
> optional at the call site is a bad idea.
>
>> 2. We could say UFCS has an implicit ref-at-callsite if needed, and will
>> not compile for rvalues.  If you think about it, 'this' is implicitly ref,
>> and UFCS is calling like the first argument is the 'this' reference.
>
> That would make using UFCS with ranges generally illegal, as most range-based
> funtions do not have ref parameters, and you generally don't want them to be
> passed by ref.

I misunderstood.  You would not need ref at callsite because it's optional.  So this actually is fine.  You don't need to do anything.

How would you prevent 'rvalue' ranges from going in?  Don't use UFCS, and put ref at callsite.

The problem with this whole rvalue/lvalue scheme is that rvalue and lvalue are not good terms to describe what we want.  Just because you can't assign to an rvalue doesn't mean you can't assign to a member of that rvalue, it could be a pointer.

> This has come up on the newsgroup before, and I really do think that having it
> as optional is worse than not having it. If it's required, then when you see
> that an argument is marked with ref, you know that the parameter is a ref
> parameter, and when you see an argument without ref, you know that the
> parameter is not a ref parameter. And the compiler enforces both, so you
> always catch it when the function changes.

That is not the point of this suggestion.  It would simply be to ensure changes from an lvalue to an rvalue don't compile.  It would only be used in those cases.

In other words, ref at callsite means "I have an lvalue".  If that changes, no compilation.

-Steve
1 2 3 4 5 6 7 8
Next ›   Last »