April 12, 2012
On Thursday, April 12, 2012 23:24:17 Andrej Mitrovic wrote:
> Currently you don't have to use address-of operator if you mark the
> extern(C) function as taking ref:

I consider that to be non-issue. You're calling C code. It's normal to then have to use C constructs. And arguably, while calling C code shouldn't be hard, it _shouldn't_ be pretty, because it's inherently unsafe.

> 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:

_This_ on the other hand is bad, and I think that it's a good argument for allowing the address of refs to be taken in @system code. Not being able to take the address of a ref to pass to a C function would be a definite problem.

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

April 13, 2012
On 13.04.2012 2:21, Andrei Alexandrescu wrote:
> 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.
>

To clarify my stance on this somewhat - I believe it just shows 2 things:
a) Sealed conatiners with rvalue returns are rapidly becoming extinct beasts with this new ref-binds-rvalues rule. It arguably might be viewed as an antipattern like declaring C++ operator[] returning non-ref where you obviously didn't meant it.
b) Apparently the whole trend of "I don't care if this an rvalue or lvalue" comes to a stop as it turns out that you do care in a lot of cases.

-- 
Dmitry Olshansky

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

April 13, 2012
I think the main purpose of rvalue reference is:
"Called function requires the address of given value, but not need to
change its value semantics."

We can never rewrite basic literals, therefore we can say that they
have constant value semantics, even if their types are mutable. And
then, it seems that rewriting literal through rvalue reference (==
temporary variable) is counter-intuitive, and less useful.
On the other hand, compound literals usually have mutable
elements/fields, so called function may use and rewrite them. It is
often useful.

More details of my proposal with an actual code:

struct S{}

void foo(const ref int v){}
void foo(const ref double v){}
void foo(const ref cdouble v){}
void foo(const ref int[] v){}
void foo(const ref int[int] v){}
void foo(const ref S v){}
void bar(      ref int v){}
void bar(      ref double v){}
void bar(      ref cdouble v){}
void bar(      ref int[] v){}
void bar(      ref int[int] v){}
void bar(      ref S v){}

void hoo(T)(const ref T v){}
void var(T)(      ref T v){}

void main()
{
    // cannot bind basic literals to mutable ref
    enum int ei = 1024;
    foo(1024);  static assert(!__traits(compiles, bar(1024)));
    hoo(1024);  static assert(!__traits(compiles, var(1024)));
    foo(ei);    static assert(!__traits(compiles, bar(ei)));
    hoo(ei);    static assert(!__traits(compiles, var(ei)));

    enum double ef = 3.14;
    foo(3.14);  static assert(!__traits(compiles, bar(3.14)));
    hoo(3.14);  static assert(!__traits(compiles, var(3.14)));
    foo(ef);    static assert(!__traits(compiles, bar(ef)));
    hoo(ef);    static assert(!__traits(compiles, var(ef)));

    enum cdouble ec = 1+1i;
  /*foo(1+1i);*/static assert(!__traits(compiles, bar(1+1i)));
  /*hoo(1+1i);*/static assert(!__traits(compiles, var(1+1i)));
    foo(ec);    static assert(!__traits(compiles, bar(ec)));
    hoo(ec);    static assert(!__traits(compiles, var(ec)));

    // can bind compound literals to mutable ref
    enum int[] ea = [1,2];
    foo([1,2]); bar([1,2]);
    hoo([1,2]); var([1,2]);
    foo(ea);    bar(ea);
    hoo(ea);    var(ea);

    enum int[int] eaa = [1:1];
    foo([1:1]); bar([1:1]);
    hoo([1:1]); var([1:1]);
    foo(eaa);   bar(eaa);
    hoo(eaa);   var(eaa);

    enum S es = S();
    foo(S());   bar(S());
    hoo(S());   var(S());
    foo(es);    bar(es);
    hoo(es);    var(es);
}

Kenji Hara

2012$BG/(B4$B7n(B13$BF|(B14:58 kenji hara <k.hara.pg@gmail.com>:
> 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

April 13, 2012
On 4/13/12 2:36 AM, Dmitry Olshansky wrote:
> To clarify my stance on this somewhat - I believe it just shows 2 things:
> a) Sealed conatiners with rvalue returns are rapidly becoming extinct
> beasts with this new ref-binds-rvalues rule. It arguably might be viewed
> as an antipattern like declaring C++ operator[] returning non-ref where
> you obviously didn't meant it.
> b) Apparently the whole trend of "I don't care if this an rvalue or
> lvalue" comes to a stop as it turns out that you do care in a lot of cases.

Agreed to both. I think the no-escape rule for ref is great, but we need to work some kinks out off it. The rvalue->lvalue needs a fair amount of work.

Andrei

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

April 13, 2012
On 4/13/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> On Thursday, April 12, 2012 23:24:17 Andrej Mitrovic wrote:
>> Currently you don't have to use address-of operator if you mark the
>> extern(C) function as taking ref:
>
> I consider that to be non-issue. You're calling C code. It's normal to then have to use C constructs. And arguably, while calling C code shouldn't be hard, it _shouldn't_ be pretty, because it's inherently unsafe.

Another benefit of allowing in/out/ref is that it serves as good documentation. Microsoft has been using this idiom for years:

http://msdn.microsoft.com/en-us/library/dd162477%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/dd144943%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/dd183370%28v=vs.85%29.aspx

Being able to mark C function parameters with actual D keywords is a win, imho. It might not make much sense to allow e.g. 'lazy', but in/out/ref is fine.

If you want to break code, they you obviously must be willing to put
the effort into fixing existing libraries. You can't have Walter & co.
advertise the language as stable and then completely break existing
code between releases. It would be pure irony to ban this feature
considering how Walter already made a thread about stopping breaking
code between releases.
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 13, 2012
On Friday, April 13, 2012 18:38:53 Andrej Mitrovic wrote:
> On 4/13/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> > On Thursday, April 12, 2012 23:24:17 Andrej Mitrovic wrote:
> >> Currently you don't have to use address-of operator if you mark the
> > 
> >> extern(C) function as taking ref:
> > I consider that to be non-issue. You're calling C code. It's normal to
> > then
> > have to use C constructs. And arguably, while calling C code shouldn't be
> > hard, it _shouldn't_ be pretty, because it's inherently unsafe.
> 
> Another benefit of allowing in/out/ref is that it serves as good documentation. Microsoft has been using this idiom for years:
> 
> http://msdn.microsoft.com/en-us/library/dd162477%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/dd144943%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/dd183370%28v=vs.85%29.aspx
> 
> Being able to mark C function parameters with actual D keywords is a win, imho. It might not make much sense to allow e.g. 'lazy', but in/out/ref is fine.
> 
> If you want to break code, they you obviously must be willing to put the effort into fixing existing libraries. You can't have Walter & co. advertise the language as stable and then completely break existing code between releases. It would be pure irony to ban this feature considering how Walter already made a thread about stopping breaking code between releases.

As of right now, it's questionable whether this is an intended feature or whether it just so happens to work. If it just so happens to work, then it's a bug, and just like any bug, when it's fixed, any code relying on it will break.

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

April 14, 2012
How about my idea, Andrei?

Kenji Hara
 2012/04/13 17:47 "kenji hara" <k.hara.pg@gmail.com>:

> I think the main purpose of rvalue reference is:
> "Called function requires the address of given value, but not need to
> change its value semantics."
>
> We can never rewrite basic literals, therefore we can say that they
> have constant value semantics, even if their types are mutable. And
> then, it seems that rewriting literal through rvalue reference (==
> temporary variable) is counter-intuitive, and less useful.
> On the other hand, compound literals usually have mutable
> elements/fields, so called function may use and rewrite them. It is
> often useful.
>
> More details of my proposal with an actual code:
>
> struct S{}
>
> void foo(const ref int v){}
> void foo(const ref double v){}
> void foo(const ref cdouble v){}
> void foo(const ref int[] v){}
> void foo(const ref int[int] v){}
> void foo(const ref S v){}
> void bar(      ref int v){}
> void bar(      ref double v){}
> void bar(      ref cdouble v){}
> void bar(      ref int[] v){}
> void bar(      ref int[int] v){}
> void bar(      ref S v){}
>
> void hoo(T)(const ref T v){}
> void var(T)(      ref T v){}
>
> void main()
> {
>    // cannot bind basic literals to mutable ref
>    enum int ei = 1024;
>    foo(1024);  static assert(!__traits(compiles, bar(1024)));
>    hoo(1024);  static assert(!__traits(compiles, var(1024)));
>    foo(ei);    static assert(!__traits(compiles, bar(ei)));
>    hoo(ei);    static assert(!__traits(compiles, var(ei)));
>
>    enum double ef = 3.14;
>    foo(3.14);  static assert(!__traits(compiles, bar(3.14)));
>    hoo(3.14);  static assert(!__traits(compiles, var(3.14)));
>    foo(ef);    static assert(!__traits(compiles, bar(ef)));
>    hoo(ef);    static assert(!__traits(compiles, var(ef)));
>
>    enum cdouble ec = 1+1i;
>  /*foo(1+1i);*/static assert(!__traits(compiles, bar(1+1i)));
>  /*hoo(1+1i);*/static assert(!__traits(compiles, var(1+1i)));
>    foo(ec);    static assert(!__traits(compiles, bar(ec)));
>    hoo(ec);    static assert(!__traits(compiles, var(ec)));
>
>    // can bind compound literals to mutable ref
>    enum int[] ea = [1,2];
>    foo([1,2]); bar([1,2]);
>    hoo([1,2]); var([1,2]);
>    foo(ea);    bar(ea);
>    hoo(ea);    var(ea);
>
>    enum int[int] eaa = [1:1];
>    foo([1:1]); bar([1:1]);
>    hoo([1:1]); var([1:1]);
>    foo(eaa);   bar(eaa);
>    hoo(eaa);   var(eaa);
>
>    enum S es = S();
>    foo(S());   bar(S());
>    hoo(S());   var(S());
>    foo(es);    bar(es);
>    hoo(es);    var(es);
> }
>
> Kenji Hara
>
> 2012$BG/(B4$B7n(B13$BF|(B14:58 kenji hara <k.hara.pg@gmail.com>:
> > 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
>


April 13, 2012
I'm busy right now, give me some time to look over it.

Thanks,

Andrei

On 4/13/12 1:39 PM, kenji hara wrote:
> How about my idea, Andrei?
>
> Kenji Hara
>
> 2012/04/13 17:47 "kenji hara" <k.hara.pg@gmail.com
> <mailto:k.hara.pg@gmail.com>>:
>
>     I think the main purpose of rvalue reference is:
>     "Called function requires the address of given value, but not need to
>     change its value semantics."
>
>     We can never rewrite basic literals, therefore we can say that they
>     have constant value semantics, even if their types are mutable. And
>     then, it seems that rewriting literal through rvalue reference (==
>     temporary variable) is counter-intuitive, and less useful.
>     On the other hand, compound literals usually have mutable
>     elements/fields, so called function may use and rewrite them. It is
>     often useful.
>
>     More details of my proposal with an actual code:
>
>     struct S{}
>
>     void foo(const ref int v){}
>     void foo(const ref double v){}
>     void foo(const ref cdouble v){}
>     void foo(const ref int[] v){}
>     void foo(const ref int[int] v){}
>     void foo(const ref S v){}
>     void bar( ref int v){}
>     void bar( ref double v){}
>     void bar( ref cdouble v){}
>     void bar( ref int[] v){}
>     void bar( ref int[int] v){}
>     void bar( ref S v){}
>
>     void hoo(T)(const ref T v){}
>     void var(T)( ref T v){}
>
>     void main()
>     {
>     // cannot bind basic literals to mutable ref
>     enum int ei = 1024;
>     foo(1024); static assert(!__traits(compiles, bar(1024)));
>     hoo(1024); static assert(!__traits(compiles, var(1024)));
>     foo(ei); static assert(!__traits(compiles, bar(ei)));
>     hoo(ei); static assert(!__traits(compiles, var(ei)));
>
>     enum double ef = 3.14;
>     foo(3.14); static assert(!__traits(compiles, bar(3.14)));
>     hoo(3.14); static assert(!__traits(compiles, var(3.14)));
>     foo(ef); static assert(!__traits(compiles, bar(ef)));
>     hoo(ef); static assert(!__traits(compiles, var(ef)));
>
>     enum cdouble ec = 1+1i;
>     /*foo(1+1i);*/static assert(!__traits(compiles, bar(1+1i)));
>     /*hoo(1+1i);*/static assert(!__traits(compiles, var(1+1i)));
>     foo(ec); static assert(!__traits(compiles, bar(ec)));
>     hoo(ec); static assert(!__traits(compiles, var(ec)));
>
>     // can bind compound literals to mutable ref
>     enum int[] ea = [1,2];
>     foo([1,2]); bar([1,2]);
>     hoo([1,2]); var([1,2]);
>     foo(ea); bar(ea);
>     hoo(ea); var(ea);
>
>     enum int[int] eaa = [1:1];
>     foo([1:1]); bar([1:1]);
>     hoo([1:1]); var([1:1]);
>     foo(eaa); bar(eaa);
>     hoo(eaa); var(eaa);
>
>     enum S es = S();
>     foo(S()); bar(S());
>     hoo(S()); var(S());
>     foo(es); bar(es);
>     hoo(es); var(es);
>     }
>
>     Kenji Hara
>
>     2012年4月13日14:58 kenji hara <k.hara.pg@gmail.com
>     <mailto:k.hara.pg@gmail.com>>:
>      > 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年4月11日13:33 Andrei Alexandrescu <andrei@erdani.com
>     <mailto: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 <mailto: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
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta
April 13, 2012
On 13 April 2012 20:14, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> On Friday, April 13, 2012 18:38:53 Andrej Mitrovic wrote:
>> On 4/13/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>> > On Thursday, April 12, 2012 23:24:17 Andrej Mitrovic wrote:
>> >> Currently you don't have to use address-of operator if you mark the
>> >
>> >> extern(C) function as taking ref:
>> > I consider that to be non-issue. You're calling C code. It's normal to
>> > then
>> > have to use C constructs. And arguably, while calling C code shouldn't be
>> > hard, it _shouldn't_ be pretty, because it's inherently unsafe.
>>
>> Another benefit of allowing in/out/ref is that it serves as good documentation. Microsoft has been using this idiom for years:
>>
>> http://msdn.microsoft.com/en-us/library/dd162477%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/dd144943%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/dd183370%28v=vs.85%29.aspx
>>
>> Being able to mark C function parameters with actual D keywords is a win, imho. It might not make much sense to allow e.g. 'lazy', but in/out/ref is fine.
>>
>> If you want to break code, they you obviously must be willing to put the effort into fixing existing libraries. You can't have Walter & co. advertise the language as stable and then completely break existing code between releases. It would be pure irony to ban this feature considering how Walter already made a thread about stopping breaking code between releases.
>
> As of right now, it's questionable whether this is an intended feature or whether it just so happens to work. If it just so happens to work, then it's a bug, and just like any bug, when it's fixed, any code relying on it will break.

Interestingly, the ref int[3] idiom is documented as working, under
'interfacing with C'.
Anything beyond that seems to be undefined.
That page seems to document dynamic arrays as _not_ working --
certainly as having no C equivalent.
_______________________________________________
dmd-beta mailing list
dmd-beta@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-beta

April 13, 2012
On Friday, April 13, 2012 22:18:16 Don Clugston wrote:
> Interestingly, the ref int[3] idiom is documented as working, under
> 'interfacing with C'.
> Anything beyond that seems to be undefined.
> That page seems to document dynamic arrays as _not_ working --
> certainly as having no C equivalent.

Which seems really backwards considering that in both case, you'd be using T* in C, and if anything, dynamic arrays are closer to that than static arrays. Personally, I'd have expected arr.ptr to be required in both cases.

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