January 15, 2012
On 01/15/2012 11:41 PM, Peter Alexander wrote:
> On 15/01/12 10:10 PM, Timon Gehr wrote:
>> Another thing that would have to be discussed: what happens to const ref
>> parameters? It is very reasonable that someone will decide to change
>> calling conventions from by value to by const ref or the other way round
>> after profiling. It is very convenient that such a change is
>> syntactically transparent to the caller and this should stay.
>
> Actually, that would be very dangerous. const ref does not have the
> privilege of being able to bind to rvalues in D like it does in C++.
>
> void foo(const ref int x) {...}
>
> foo(1); // this is legal in C++, but illegal in D
>

Who on earth wants to change an int parameter from by value to by const ref? struct literals can bind to const ref parameters so there is absolutely no issue.

> In case, const ref would not require the ref at call site because
> there's no danger of it being modified.
>

The semantics are still not the same.
January 15, 2012
On 01/15/2012 10:39 PM, Nick Sabalausky wrote:
> "Alex Rønne Petersen"<xtzgzorex@gmail.com>  wrote in message
> news:jeukpm$168v$1@digitalmars.com...
>> Hi,
>>
>> I don't know how many times I've made the mistake of passing a local
>> variable to a function which takes a 'ref' parameter. Suddenly, local
>> variables/fields are just mutating out of nowhere, because it's not at all
>> obvious that a function you're calling is taking a 'ref' parameter. This
>> is particularly true for std.utf.decode().
>>
>> Yes, I realize I could look at the function declaration. Yes, I could read
>> the docs too. But that doesn't prevent me from forgetting that a function
>> takes a 'ref' parameter, and then doing the mistake again. The damage is
>> done, and the time is wasted.
>>
>> I think D should allow 'ref' on call sites to prevent these mistakes. For
>> example:
>>
>> string str = ...;
>> size_t pos;
>> auto chr = std.utf.decode(str, ref pos);
>>
>> Now it's much more obvious that the parameter is passed by reference and
>> is going to be mutated.
>>
>> Ideally, this would not be optional, but rather *required*, but I realize
>> that such a change would break a *lot* of code, so that's probably not a
>> good idea.
>>
>> Thoughts?
>>
>
> Yes, this is one of the few things I always thought C# got right and D got
> wrong.
>

I think both C# and D got it right.

> That said though, I haven't personally run into this problem, and I've
> gotten used to not having "ref" or "out" on the caller's side. I wouldn't be
> opposed to the change though, even just as an optional warning.
>
>

January 15, 2012
On 01/15/2012 11:36 PM, Timon Gehr wrote:
> On 01/15/2012 11:41 PM, Peter Alexander wrote:
>> On 15/01/12 10:10 PM, Timon Gehr wrote:
>>> Another thing that would have to be discussed: what happens to const ref
>>> parameters? It is very reasonable that someone will decide to change
>>> calling conventions from by value to by const ref or the other way round
>>> after profiling. It is very convenient that such a change is
>>> syntactically transparent to the caller and this should stay.
>>
>> Actually, that would be very dangerous. const ref does not have the
>> privilege of being able to bind to rvalues in D like it does in C++.
>>
>> void foo(const ref int x) {...}
>>
>> foo(1); // this is legal in C++, but illegal in D
>>
>
> Who on earth wants to change an int parameter from by value to by const
> ref? struct literals can bind to const ref parameters so there is
> absolutely no issue.
>
>> In case, const ref would not require the ref at call site because
>> there's no danger of it being modified.
>>
>
> The semantics are still not the same.

(Even the claim that there is no danger of it being modified is plain wrong)
January 15, 2012
On 15/01/12 10:36 PM, Timon Gehr wrote:
> On 01/15/2012 11:41 PM, Peter Alexander wrote:
>> On 15/01/12 10:10 PM, Timon Gehr wrote:
>>> Another thing that would have to be discussed: what happens to const ref
>>> parameters? It is very reasonable that someone will decide to change
>>> calling conventions from by value to by const ref or the other way round
>>> after profiling. It is very convenient that such a change is
>>> syntactically transparent to the caller and this should stay.
>>
>> Actually, that would be very dangerous. const ref does not have the
>> privilege of being able to bind to rvalues in D like it does in C++.
>>
>> void foo(const ref int x) {...}
>>
>> foo(1); // this is legal in C++, but illegal in D
>>
>
> Who on earth wants to change an int parameter from by value to by const
> ref? struct literals can bind to const ref parameters so there is
> absolutely no issue.

Are you sure about struct literals binding to const ref? I can't find anything in the language spec or TDPL that supports that claim.

In fact, TDPL says:

"If a function expects a ref, it accepts only "real" data, not temporaries; anything that's not an lvalue is rejected during compilation"

Unfortunately it doesn't say anything explicitly about struct literals or const ref, but that would lead me to believe that they fall under the same rule.

DMD allows struct literals to bind to const ref, but then again it also allows them to bind to ref, so I'm not sure how reliable that is.

This should probably be clarified. It's kind of important.
January 15, 2012
On 01/16/2012 12:39 AM, Peter Alexander wrote:
> On 15/01/12 10:36 PM, Timon Gehr wrote:
>> On 01/15/2012 11:41 PM, Peter Alexander wrote:
>>> On 15/01/12 10:10 PM, Timon Gehr wrote:
>>>> Another thing that would have to be discussed: what happens to const
>>>> ref
>>>> parameters? It is very reasonable that someone will decide to change
>>>> calling conventions from by value to by const ref or the other way
>>>> round
>>>> after profiling. It is very convenient that such a change is
>>>> syntactically transparent to the caller and this should stay.
>>>
>>> Actually, that would be very dangerous. const ref does not have the
>>> privilege of being able to bind to rvalues in D like it does in C++.
>>>
>>> void foo(const ref int x) {...}
>>>
>>> foo(1); // this is legal in C++, but illegal in D
>>>
>>
>> Who on earth wants to change an int parameter from by value to by const
>> ref? struct literals can bind to const ref parameters so there is
>> absolutely no issue.
>
> Are you sure about struct literals binding to const ref? I can't find
> anything in the language spec or TDPL that supports that claim.
>
> In fact, TDPL says:
>
> "If a function expects a ref, it accepts only "real" data, not
> temporaries; anything that's not an lvalue is rejected during compilation"
>

Well, struct literals are lvalues, at least in DMD.

> Unfortunately it doesn't say anything explicitly about struct literals
> or const ref, but that would lead me to believe that they fall under the
> same rule.
>
> DMD allows struct literals to bind to const ref, but then again it also
> allows them to bind to ref, so I'm not sure how reliable that is.
>
> This should probably be clarified. It's kind of important.

I agree, but banning it would be an arbitrary and pointless restriction.
January 15, 2012
On Monday, January 16, 2012 00:41:14 Timon Gehr wrote:
> Well, struct literals are lvalues, at least in DMD.

Yeah. I don't understand that. I've argued about it with Walter before. Apparently they are in C++ as well. I don't understand it. It makes it so that

void func(ref S val)
S bar();

works with

func(S(42));

but not

func(bar());

It seems completely arbitrary to me that it works this way and has IMHO _zero_ benefits. And I know that newbies have run into the problem and been completely confused by it (e.g. http://stackoverflow.com/questions/6986175/const-ref-and- rvalue-in-d ). _I_'ve been confused by it. I was stunned to find out that there was _any_ difference in the language between a struct literal and an identical struct returned from a function.

It's not as big an issue in C++, because using & is fairly rare in C++ unless its const, and const & will take temporaries. But in D, it's _definitely_ an issue IMHO. I really think that struct literals should be considered rvalues. I do _not_ understand why they aren't or why anyone ever thought that it was a good idea for them to be lvalues.

- Jonathan M Davis
January 16, 2012
On Sunday, January 15, 2012 14:36:53 Alex Rønne Petersen wrote:
> Thoughts?

This was discussed before, and I'm still completely against it. It _only_ has value IMHO if it's required, and even then, I don't like the idea.

If it's _not_ required, then you don't know _still_ don't know whether a function takes a ref or not. The lack of ref at the call site means _nothing_. Does

func(var);

alter var? You can't know. If it's

func(ref var);

then yes, you _do_ know that it's being altered. But this just gives you a false sense of security. You _still_ need to check _every_ function call which isn't marked with ref whether it takes its arguments by ref or not. If it were required, then you would know that

func(var);

doesn't take var by ref and that

func(ref var);

_does_ take var by ref. So, in that case, it's _not_ a false sense of security. It _actually_ guarantees something. So, it _does_ have some value in that case. But as long as it's optional, it's worse than not having it IMHO.

Now, personally, I don't like it regardless. It's makes function calls that much noisier at minimal benefit. Yes, upon occasion, I screw up and don't realize that a function takes an argument by ref, but that's something that I _should_ know. It has a definite effect on what the function does, and I should be aware of it.

So, I'm completely against this feature.

- Jonathan M Davis
January 16, 2012
El 15/01/2012 20:04, Tobias Pankrath escribió:
>> I also know that people dislike using reference parameters in C++ due to
>> the lack of visibility at the call site (causing them to use pointers).
>
> Which is true for me. Every single one of my reference parameters is const
> ref or pointer.

swap(ref a, ref b); //  ??

No, thanks.

swap(a, b); // obvious that the arguments will be mutated, and cleaner
January 16, 2012
On 15/01/12 11:56 PM, Jonathan M Davis wrote:
> On Monday, January 16, 2012 00:41:14 Timon Gehr wrote:
>> Well, struct literals are lvalues, at least in DMD.
>
> Yeah. I don't understand that. I've argued about it with Walter before.
> Apparently they are in C++ as well. I don't understand it. It makes it so that

In C++, struct literals are rvalues. C++ just has a special rule that const references can bind to rvalues (but non-const references cannot), and another special rule that when a const reference binds to a temporary it extends the life of the temporary.

The benefit in C++ is so that you can write one function that takes a const reference and it works with rvalues as well as lvalues. Taking by value would be too expensive a lot of the time.
January 16, 2012
On 01/16/2012 01:30 AM, Peter Alexander wrote:
> On 15/01/12 11:56 PM, Jonathan M Davis wrote:
>> On Monday, January 16, 2012 00:41:14 Timon Gehr wrote:
>>> Well, struct literals are lvalues, at least in DMD.
>>
>> Yeah. I don't understand that. I've argued about it with Walter before.
>> Apparently they are in C++ as well. I don't understand it. It makes it
>> so that
>
> In C++, struct literals are rvalues. C++ just has a special rule that
> const references can bind to rvalues (but non-const references cannot),
> and another special rule that when a const reference binds to a
> temporary it extends the life of the temporary.
>

In C++, a struct literal can be on the lhs of an expression (because of the implicit copy assignment operator) but you cannot take it's address unless you pass it by const& ;D

> The benefit in C++ is so that you can write one function that takes a
> const reference and it works with rvalues as well as lvalues. Taking by
> value would be too expensive a lot of the time.

In D there is no such thing as a C++ const reference, therefore I think it is reasonable that struct literals are lvalues.