April 13, 2012
Interesting thing with non-escaping ref is that making truly unsealed containers is hard while writing sealed ones made easier(and that's a good thing btw).

But the prime case for specifically unsealed containers is interfacing with C code,  it's still there and it's a big niche.
(data structures use in OpenGL, OpenCL and whatnot)

And in order for &container[idx] to seamlessly compile we might try the old trick - return a proxy that hides the pointer within.
Problem is we don't have an overloaded unary & (again it's a good thing).
Another way is to abuse slice operator: container[idx..$] which is then implicitly convertible to a pointer we need so badly.
(yes, I'm talking @system here) Still it's breaking C-styled code base.
And  since we started breaking we might as well end up with container.addrOf(idx) or some other helper along the lines.

So by the end of day unsealed containers do lose some nice plain C-like look & feel. -1 reason to actually use them ;)

-- 
Dmitry Olshansky

_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 12, 2012
On 4/12/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> Why do you need more than just normal pointers? Because of this proposal making taking the address of a ref illegal?

Yeah. For example:

extern(C) void c_modify_int(int* x) { }

void modify_int(ref int x)
{
    c_modify_int(&x);
}

void main()
{
    int x;
    modify_int(x);
}

Currently you don't have to use address-of operator if you mark the
extern(C) function as taking ref:

extern(C) void c_modify_int(ref int x) { }
void modify_int(ref int x)
{
    c_modify_int(x);
}

But if both of these get banned, the only way to pass by reference while still keeping the same API would be to create a new temporary:

extern(C) void c_modify_int(int* x) { }
void modify_int(ref int x)
{
    int y = x;
    c_modify_int(&y);
    x = y;
}

Can this be optimized by the compiler? I don't know. It sure makes for
some ugly code, especially if the C function takes multiple pointer
arguments. I don't know how many libraries depend on working 'ref' on
C functions and/or taking address of a reference, but banning 'ref' on
C functions would break the existing wxD bindings.
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 12, 2012
Le 2012-04-12 à 17:24, Andrej Mitrovic a écrit :

> Currently you don't have to use address-of operator if you mark the
> extern(C) function as taking ref:
> 
> extern(C) void c_modify_int(ref int x) { }
> void modify_int(ref int x)
> {
>    c_modify_int(x);
> }

Even if declaring C functions with ref is allowed, it can sometime be a problem to declare C functions like that. Not only it changes the usage, but also it's not too rare to see pointer parameters like this accepting a null pointer as a way to make the parameter optional, which ref won't let you do.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/



_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 12, 2012
I still want to say, extern(C) does not mean C function.  It means C linkage/calling convention.  The function can easily be implemented in D (druntime is full of this).

-Steve




>________________________________
> From: Michel Fortin <michel.fortin@michelf.com>
>To: Discuss the dmd beta releases for D <dmd-beta@puremagic.com>
>Sent: Thursday, April 12, 2012 5:34 PM
>Subject: Re: [dmd-beta] rvalue references
> 
>Le 2012-04-12 à 17:24, Andrej Mitrovic a écrit :
>
>> Currently you don't have to use address-of operator if you mark the
>> extern(C) function as taking ref:
>> 
>> extern(C) void c_modify_int(ref int x) { }
>> void modify_int(ref int x)
>> {
>>    c_modify_int(x);
>> }
>
>Even if declaring C functions with ref is allowed, it can sometime be a problem to declare C functions like that. Not only it changes the usage, but also it's not too rare to see pointer parameters like this accepting a null pointer as a way to make the parameter optional, which ref won't let you do.
>
>-- 
>Michel Fortin
>michel.fortin@michelf.com
>http://michelf.com/
>
>
>
>_______________________________________________
>dmd-beta mailing list
>dmd-beta@puremagic.com
>http://lists.puremagic.com/mailman/listinfo/dmd-beta
>
>
>

April 12, 2012
On 4/12/12, Michel Fortin <michel.fortin@michelf.com> wrote:
> Even if declaring C functions with ref is allowed, it can sometime be a problem to declare C functions like that. Not only it changes the usage, but also it's not too rare to see pointer parameters like this accepting a null pointer as a way to make the parameter optional, which ref won't let you do.

For C, yes, but for C++ wrappers it's usually the D wrapper code that
implements default arguments, not the C function declarations.
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 12, 2012
On 4/12/12 3:11 PM, Dmitry Olshansky wrote:
> Interesting thing with non-escaping ref is that making truly unsealed
> containers is hard while writing sealed ones made easier(and that's a
> good thing btw).

There is a liability here however. Today, people who don't want to allow changes to their containers or ranges would routinely return rvalues from e.g. front().

If we allow function results to bind to ref parameters, people would think they modify stuff when in fact they don't do anything. Consider:

void swap(T)(ref T lhs, ref T rhs);
...
swap(r1.front, r2.front);

The user thinks the fronts of the ranges are swapped but nothing happens.

So we don't want to allow function results (including property results) to bind to ref parameters.


Andrei

_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 13, 2012
On 13.04.2012 1:50, Andrei Alexandrescu wrote:
> On 4/12/12 3:11 PM, Dmitry Olshansky wrote:
>> Interesting thing with non-escaping ref is that making truly unsealed
>> containers is hard while writing sealed ones made easier(and that's a
>> good thing btw).
>
> There is a liability here however. Today, people who don't want to allow changes to their containers or ranges would routinely return rvalues from e.g. front().
>
> If we allow function results to bind to ref parameters, people would think they modify stuff when in fact they don't do anything. Consider:
>
> void swap(T)(ref T lhs, ref T rhs);
> ...
> swap(r1.front, r2.front);
>
> The user thinks the fronts of the ranges are swapped but nothing happens.
>
I agree with the problem. Yet when you pull out an atomic bomb to solve it I humbly take out a scalpel.
The problem is with swap - it is meaningless for rvalues. Solution? Just declare this very same intent:

void swap(T)(T lhs, T rhs){
    static assert(false, "swap of rvalues has no effect");
}

void swap(T)(ref T lhs, ref T rhs);
{
... //same trustworthy swap
}

> So we don't want to allow function results (including property results) to bind to ref parameters.
>
???
I really don't get this at all. Cripple the proposal at its best? And how it's different from:

swap(+a.b, +func()); // it's meaningless because it's _swap_, i.e. it's semantic side of things tied to' swap'

> -- Dmitry Olshansky
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 12, 2012
On 4/12/12 5:16 PM, Dmitry Olshansky wrote:
> void swap(T)(T lhs, T rhs){
> static assert(false, "swap of rvalues has no effect");
> }
>
> void swap(T)(ref T lhs, ref T rhs);
> {
> ... //same trustworthy swap
> }

I'm not sure how well this scales. We're adding as much boilerplate as functionality here.


Andrei
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 12, 2012
On Apr 12, 2012, at 5:50 PM, Andrei Alexandrescu <andrei@erdani.com> wrote:

> On 4/12/12 3:11 PM, Dmitry Olshansky wrote:
>> Interesting thing with non-escaping ref is that making truly unsealed containers is hard while writing sealed ones made easier(and that's a good thing btw).
> 
> There is a liability here however. Today, people who don't want to allow changes to their containers or ranges would routinely return rvalues from e.g. front().
> 
> If we allow function results to bind to ref parameters, people would think they modify stuff when in fact they don't do anything. Consider:
> 
> void swap(T)(ref T lhs, ref T rhs);
> ...
> swap(r1.front, r2.front);
> 
> The user thinks the fronts of the ranges are swapped but nothing happens.
> 
> So we don't want to allow function results (including property results) to bind to ref parameters.

You could still allow binding to const ref parameters.
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 13, 2012
I think to avoid some useless case, I'd like to add a rule.

In basic, literals (e.g. 10, 3.14, "hello") in D are typed as mutable.
typeof(10) == int
typeof(3.14) == double
typeof("hello") == immutable(char)[]   // array itself is mutable

Then, with new rvalue reference mechanism, literals are assigned to mutable temporaries, and be bound to ref.

void foo(ref int n){}
foo(10);
// same as int tmp = 10; foo(tmp);

But it is less useful behavior.

I propose that if rvalue reference binding is needed, and the rvalue is built-in literal, its type is treated as const.

void foo(ref int n){}
foo(10);
// same as const(int) tmp = 10; foo(tmp);
// tmp is const, and binding const variable to mutable ref is illegal,
then raises an error.

Finally, I don't know we should apply this rule to struct literal too. It sounds good, but I afraid that is too restrict.

Kenji Hara

2012$BG/(B4$B7n(B11$BF|(B13:33 Andrei Alexandrescu <andrei@erdani.com>:
> On 4/10/12 7:57 PM, Walter Bright wrote:
>>
>> 2.
>> double& d;
>> int i;
>> void foo() {
>> d = i;
>> }
>
>
> This example is off; a reference can't be rebound. The relevant example is:
>
> void increment(double& d)
> {
>    ++d;
> }
> ...
> int i;
> increment(i);
>
> People think the int has been incremented, but in fact a useless temporary has.
>
> The discussion about what to do in D has been a bit longer and more far-reaching than Walter mentioned.
>
> The long-term plan is to never let the address of a ref escape the expression in which the ref occurs. That means in essence that user code can't take the address of a ref.
>
> Once that is in place, we will know for sure that all ref passed into and returned by functions will not escape the immediate expression in which that happens - great for safe code.
>
> People who need to take &this and escape it (e.g in linked lists implemented with struct) will not be able to; they'll have to use static functions and pointers for that. Generally any work that involves escaping pointers will have to use pointers, not references.
>
> I think this puts us in a very good spot:
>
> 1. Safe code will be able to use ref liberally
>
> 2. Functions will be able to return ref knowing the ref won't survive the current expression. This is awesome for sealed containers - safe and fast.
>
> What does this have to do with rvalues and lvalues? It means that with the appropriate precautions, we _can_ transform rvalues into lvalues, because we know their address can't unsafely escape.
>
> There is one precautions to take: we should never convert a value of type T to a ref of another type U. That would cause the problems we learned from C++. There are 3 cases of such implicit conversions:
>
> 1. built-in numerics, e.g. an int should not convert to a ref double.
>
> 2. Class inheritance, e.g. a Widget should not convert to a ref Object.
>
> 3. alias this, e.g.:
>
> struct T {}
> struct A { @property T fun(); alias fun this; }
> void fun(ref T);
> ...
> A a;
> fun(a); // should not work
>
>
> I think this all holds water. Destroy!
>
> Andrei
>
>
> _______________________________________________
> dmd-beta mailing list
> dmd-beta@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta