www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP25 draft available for destruction

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Probably it'll need a fair amount of tweaking. Anyhow it's in 
destroyable form.

http://wiki.dlang.org/DIP25


Thanks,

Andrei
Feb 05 2013
next sibling parent kenji hara <k.hara.pg gmail.com> writes:
--089e013d12c0a97f9d04d50a05bc
Content-Type: text/plain; charset=UTF-8

2013/2/6 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>

 Probably it'll need a fair amount of tweaking. Anyhow it's in destroyable
 form.

 http://wiki.dlang.org/DIP25

Hmm, this is much reasonable. In recent, I had wrote and post a compiler extension to reinforce a kind of trait which related to pure function. I call the trait "isolated", and that means "Whether any reachable indirections from parameters does not appear in the returned value". https://github.com/D-Programming-Language/dmd/pull/1519 With my patch, such as following cases can be detected. struct S { int* ptr; } S foo(int* ptr) pure; S bar(const int* ptr) pure; void main() { int n; immutable S s = foo(&n); // implicit conversion from S to immutable S is _diallowed_. // Because &n may appear in foo's returned value. immutable S s = bar(&n); // implicit conversion from S to immutable S is _allowed_. // Because &n never appear in bar's returned value. // (compiler assumes that bar doesn't do any un- safe operations, e.g. cast(int*)ptr) } As far as I see, the contained essence in the DIP is much similar to the "isolated" traits. So I can say that it is *implementable*. Kenji Hara --089e013d12c0a97f9d04d50a05bc Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2013= /2/6 Andrei Alexandrescu <span dir=3D"ltr">&lt;<a href=3D"mailto:SeeWebsite= ForEmail erdani.org" target=3D"_blank">SeeWebsiteForEmail erdani.org</a>&gt= ;</span><br> <blockquote class=3D"gmail_quote" style=3D"margin-top:0px;margin-right:0px;= margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color= :rgb(204,204,204);border-left-style:solid;padding-left:1ex">Probably it&#39= ;ll need a fair amount of tweaking. Anyhow it&#39;s in destroyable form.<br=

<br> <a href=3D"http://wiki.dlang.org/DIP25" target=3D"_blank">http://wiki.dlang= .org/DIP25</a></blockquote><div><br></div>Hmm, this is much reasonable.<div=
<br></div><div><div>In recent, I had wrote and post a compiler extension t=

trait &quot;isolated&quot;, and that means &quot;Whether any reachable ind= irections from parameters does not appear in the returned value&quot;.</div=

age/dmd/pull/1519">https://github.com/D-Programming-Language/dmd/pull/1519<= /a><br></div><div><br></div><div>With my patch, such as following cases can= be detected.</div> <div><br></div><div>struct S { int* ptr; }<br></div><div><div><div>S foo(in= t* ptr) pure;</div><div>S bar(const int* ptr) pure;</div><div><br></div>voi= d main() {<br class=3D""><div>=C2=A0 int n;</div><div>=C2=A0 immutable S s = =3D foo(&amp;n);</div> <div>=C2=A0 // implicit conversion from S to immutable S is _diallowed_.</d= iv><div>=C2=A0 // Because &amp;n may appear in=C2=A0foo&#39;s=C2=A0returned= value.</div><div><br></div><div>=C2=A0 immutable S s =3D bar(&amp;n);<br><= /div><div>=C2=A0 // implicit conversion from S to immutable S is _allowed_.= </div> <div>=C2=A0 // Because &amp;n never appear in=C2=A0bar&#39;s=C2=A0returned = value.</div><div>=C2=A0 // (compiler assumes that bar doesn&#39;t do any un= - safe operations, e.g. cast(int*)ptr)</div></div></div><div>}</div><div><b= r></div><div>As far as I see, the contained essence in the DIP is much simi= lar to the &quot;isolated&quot; traits.</div> <div class=3D"gmail_extra">So I can say that it is *implementable*.</div><d= iv class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">Kenji Hara<br=
</div></div></div></div>

--089e013d12c0a97f9d04d50a05bc--
Feb 06 2013
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
Am Wed, 06 Feb 2013 02:38:17 -0500
schrieb Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:

 Probably it'll need a fair amount of tweaking. Anyhow it's in 
 destroyable form.
 
 http://wiki.dlang.org/DIP25
 
 
 Thanks,
 
 Andrei

Sounds good. Regarding rule 2.2: I think somebody already said that classes could be allocated on the stack but I guess we can't do anything about that. At least in safe code placing a class on the stack should be illegal though, so we can partially avoid the problem there. If we have such a special rule for classes would it also make sense to have a similar rule for struct*?
Feb 06 2013
prev sibling next sibling parent reply Chad Joan <chadjoan gmail.com> writes:
On 02/06/2013 02:38 AM, Andrei Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

This is probably reasonably, but I'm having trouble fully comprehending it. Once I get to the "Typechecking rules" section and dig into the nitty-gritty, it seems to be written in a way that discusses what is allowed, but only briefly hints at what is disallowed. It is not immediately clear to me how this would impact my code. My interpretation so far is that the only difference between DIP25 and current D code is that we won't be allowed to pass stack variables (including by-value/copied parameters) into ref parameters. HTH
Feb 06 2013
next sibling parent reply Chad Joan <chadjoan gmail.com> writes:
On 02/06/2013 09:48 AM, Chad Joan wrote:
 Once I get to the "Typechecking rules" section and dig into the
 nitty-gritty, it seems to be written in a way that discusses what is
 allowed, but only briefly hints at what is disallowed. It is not
 immediately clear to me how this would impact my code.

I should be more clear myself: I mean "Typechecking rules" and everything that follows it.
Feb 06 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 9:49 AM, Chad Joan wrote:
 On 02/06/2013 09:48 AM, Chad Joan wrote:
 Once I get to the "Typechecking rules" section and dig into the
 nitty-gritty, it seems to be written in a way that discusses what is
 allowed, but only briefly hints at what is disallowed. It is not
 immediately clear to me how this would impact my code.

I should be more clear myself: I mean "Typechecking rules" and everything that follows it.

Yah, we need more examples. As for what's disallowed, in a way it's "simple" - everything that's not allowed is disallowed :o). We definitely should add discussion of disallowed uses. Andrei
Feb 06 2013
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 9:48 AM, Chad Joan wrote:
 My interpretation so far is that the only difference between DIP25 and
 current D code is that we won't be allowed to pass stack variables
 (including by-value/copied parameters) into ref parameters.

Hmm, I need to make things clearer. That's covered plainly in 1.1. You get to pass down stack variables and by-value parameters down to functions taking ref. You won't be able to return them up, no matter what you (safely) try. Andrei
Feb 06 2013
prev sibling next sibling parent "Zach the Mystic" <reachBUTMINUSTHISzach gOOGLYmail.com> writes:
On Wednesday, 6 February 2013 at 07:38:17 UTC, Andrei 
Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in 
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

All of the 'fine' ones are fine. Which leaves how one might invoke the 'unfine' ones. The language must make a choice between restricted simplicity and flexible complexity. If it chooses flexibility, the function signature must give a clue as to what the return value contains. 'out' return values and 'scope' parameters will give the clues it needs. Here are all the 'unfine' functions listed: ref T gun(ref T); struct S { int a; T b; } ref S iun(ref S); ref T caller(bool condition, ref T v1, ref S v2, T v3, S v4) { T v5; S v6; // Not fine, bound to locals // if (condition) return gun(v3); // if (condition) return gun(v4.b); // if (condition) return gun(v5); // if (condition) return gun(v6.b); // Not fine, bound to locals // if (condition) return iun(v4); // if (condition) return iun(v6); } Say gun's actual implementation is: ref T gun(ref T a) { auto noo = new T; noo = a; return noo; } You can' tell from the function signature that the return value of this function is good to go, so the call 'return gun(v3);' above would be disallowed even though it didn't need to be. If you marked the signature with 'out', the caller knows it's good to go, and the compiler can statically prevent the function from returning one of its ref parameters. 'out' can be made to imply 'ref' in any case where the type is not inherently a reference anyway. out T gun(ref T a) { return new T; // Pass return a; // Error } This will solve all problems, except for the very rare corner case when you need to assert fined-grained control over exactly which ref parameters are safe and which are not. 'scope' comes to the rescue here. ref int fud(ref int a, scope int b) { a += b; return a; // Pass return b; // Error } ref int elmer(ref int f) { int v; return fud(f, v); // Passes return fud(v, f); // Fails } An 'out' return value simply marks all its 'ref' parameters 'scope' underneath the hood, so there will never be a need for both 'out' and 'scope' in the same signature. Since 'scope' is useless if its not a reference, it implies 'ref' also. I'm pretty sure this is the best way to make the language completely flexible. I don't anticipate an easier way to get it done, and therefore, to my mind at least, the choice is between simple-but-limited and flexible-and-complicated.
Feb 06 2013
prev sibling next sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 06.02.2013 08:38, schrieb Andrei Alexandrescu:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

What I don't get is, why is it better to have a function "addressOf(value)" that does exactly the same as &value? Expect that it is more text to type? Why is addressOf(value) more explicit then &value? Kind Regards Benjamin Thaut
Feb 06 2013
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 12:33 PM, Benjamin Thaut wrote:
 Am 06.02.2013 08:38, schrieb Andrei Alexandrescu:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

What I don't get is, why is it better to have a function "addressOf(value)" that does exactly the same as &value? Expect that it is more text to type? Why is addressOf(value) more explicit then &value?

A good part of that is the recent debate on what &func should do (take the address of the function vs. the address of its result). With the unsafe meaning out of the way, only the safe one is eligible. Andrei
Feb 06 2013
next sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 06.02.2013 18:36, schrieb Andrei Alexandrescu:
 On 2/6/13 12:33 PM, Benjamin Thaut wrote:
 Am 06.02.2013 08:38, schrieb Andrei Alexandrescu:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

What I don't get is, why is it better to have a function "addressOf(value)" that does exactly the same as &value? Expect that it is more text to type? Why is addressOf(value) more explicit then &value?

A good part of that is the recent debate on what &func should do (take the address of the function vs. the address of its result). With the unsafe meaning out of the way, only the safe one is eligible. Andrei

Ok that makes sense, you might want to add that as a explanation to the DIP. So the &value expression would only be left for taking addresses of functions? Wouldn't it make more sense to do it the other way around? E.g. create some utilty function that is only there for taking the address of functions and disallowing to do so by using &func? Kind Regards Benjamin Thaut
Feb 06 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 12:40 PM, Benjamin Thaut wrote:
 So the &value expression would only be left for taking addresses of
 functions? Wouldn't it make more sense to do it the other way around?
 E.g. create some utilty function that is only there for taking the
 address of functions and disallowing to do so by using &func?

I don't think that would work without adding new keywords. Andrei
Feb 06 2013
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 06.02.2013 18:50, schrieb Andrei Alexandrescu:
 On 2/6/13 12:40 PM, Benjamin Thaut wrote:
 So the &value expression would only be left for taking addresses of
 functions? Wouldn't it make more sense to do it the other way around?
 E.g. create some utilty function that is only there for taking the
 address of functions and disallowing to do so by using &func?

I don't think that would work without adding new keywords. Andrei

Whats so bad about adding a new keyword for this? I fear that newcomers will find taking addresses pretty inconsistens if we implement this proposal. Because the language will have the take address operator "&" they know from c++, but it only works in some special cases. For all other cases addressOf has to be used. It would be much more consistent if you could use the "&" operator for everything but taking the address of a function. That would be more consistent in my opinion. Lately I'm getting the feeling that D 2.0 is becoming a collection of hacks to workaround issues which could be solved by adding new keywords or doing other major changes. (like all the stuff that starts with __) Kind Regards Benjamin Thaut
Feb 06 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 1:39 PM, Benjamin Thaut wrote:
 Am 06.02.2013 18:50, schrieb Andrei Alexandrescu:
 On 2/6/13 12:40 PM, Benjamin Thaut wrote:
 So the &value expression would only be left for taking addresses of
 functions? Wouldn't it make more sense to do it the other way around?
 E.g. create some utilty function that is only there for taking the
 address of functions and disallowing to do so by using &func?

I don't think that would work without adding new keywords. Andrei

Whats so bad about adding a new keyword for this?

This is an ill-posed question. A keyword should justify its utility, not prove it doesn't harm.
 I fear that newcomers will find taking addresses pretty inconsistens if
 we implement this proposal. Because the language will have the take
 address operator "&" they know from c++, but it only works in some
 special cases. For all other cases addressOf has to be used. It would be
 much more consistent if you could use the "&" operator for everything
 but taking the address of a function. That would be more consistent in
 my opinion.

It would be more consistent with C++, but less so with the notion of safety. I find it very consistent that all uses of &expression are safe, and this is the kind of consistency Walter and I believe is worth aiming for.
 Lately I'm getting the feeling that D 2.0 is becoming a collection of
 hacks to workaround issues which could be solved by adding new keywords
 or doing other major changes. (like all the stuff that starts with __)

I can't help how you feel, but I think you're wrong here and I don't know what other cases you're referring to. Andrei
Feb 06 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/06/2013 08:12 PM, Andrei Alexandrescu wrote:
 On 2/6/13 1:39 PM, Benjamin Thaut wrote:
 Am 06.02.2013 18:50, schrieb Andrei Alexandrescu:
 On 2/6/13 12:40 PM, Benjamin Thaut wrote:
 So the &value expression would only be left for taking addresses of
 functions? Wouldn't it make more sense to do it the other way around?
 E.g. create some utilty function that is only there for taking the
 address of functions and disallowing to do so by using &func?

I don't think that would work without adding new keywords. Andrei

Whats so bad about adding a new keyword for this?

This is an ill-posed question. A keyword should justify its utility, not prove it doesn't harm.
 I fear that newcomers will find taking addresses pretty inconsistens if
 we implement this proposal. Because the language will have the take
 address operator "&" they know from c++, but it only works in some
 special cases. For all other cases addressOf has to be used. It would be
 much more consistent if you could use the "&" operator for everything
 but taking the address of a function. That would be more consistent in
 my opinion.

It would be more consistent with C++, but less so with the notion of safety. I find it very consistent that all uses of &expression are safe, and this is the kind of consistency Walter and I believe is worth aiming for.

So you are saying this should compile?: struct S{ int x; int foo() safe{ return x; } } int delegate() safe foo() safe{ S s; return &s.foo; }
 Lately I'm getting the feeling that D 2.0 is becoming a collection of
 hacks to workaround issues which could be solved by adding new keywords
 or doing other major changes. (like all the stuff that starts with __)

I can't help how you feel, but I think you're wrong here and I don't know what other cases you're referring to.

+1.
Feb 06 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 5:05 PM, Timon Gehr wrote:
 On 02/06/2013 08:12 PM, Andrei Alexandrescu wrote:
 It would be more consistent with C++, but less so with the notion of
 safety. I find it very consistent that all uses of &expression are safe,
 and this is the kind of consistency Walter and I believe is worth aiming
 for.

So you are saying this should compile?: struct S{ int x; int foo() safe{ return x; } } int delegate() safe foo() safe{ S s; return &s.foo; }

Yah, it should, and it also should detect the escape and allocate foo's frame on the heap. Andrei
Feb 06 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/06/2013 11:14 PM, Andrei Alexandrescu wrote:
 On 2/6/13 5:05 PM, Timon Gehr wrote:
 On 02/06/2013 08:12 PM, Andrei Alexandrescu wrote:
 It would be more consistent with C++, but less so with the notion of
 safety. I find it very consistent that all uses of &expression are safe,
 and this is the kind of consistency Walter and I believe is worth aiming
 for.

So you are saying this should compile?: struct S{ int x; int foo() safe{ return x; } } int delegate() safe foo() safe{ S s; return &s.foo; }

Yah, it should, and it also should detect the escape and allocate foo's frame on the heap. Andrei

I see. Generally? Eg. this detects the escape and allocates as well?: S* foo() safe{ S s; return &s; }
Feb 06 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 5:22 PM, Timon Gehr wrote:
 I see. Generally?
 Eg. this detects the escape and allocates as well?:

 S* foo() safe{
 S s;
 return &s;
 }

I think I'm starting to see what you're doing there :o). Andrei
Feb 06 2013
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 12:36 PM, Andrei Alexandrescu wrote:
 On 2/6/13 12:33 PM, Benjamin Thaut wrote:
 Am 06.02.2013 08:38, schrieb Andrei Alexandrescu:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

What I don't get is, why is it better to have a function "addressOf(value)" that does exactly the same as &value? Expect that it is more text to type? Why is addressOf(value) more explicit then &value?

A good part of that is the recent debate on what &func should do (take the address of the function vs. the address of its result). With the unsafe meaning out of the way, only the safe one is eligible.

Added a dedicated section to the DIP: http://goo.gl/xkIXb Andrei
Feb 06 2013
prev sibling next sibling parent "Zach the Mystic" <reachBUTMINUSTHISzach gOOGLYmail.com> writes:
On Wednesday, 6 February 2013 at 17:50:06 UTC, Andrei 
Alexandrescu wrote:
 A good part of that is the recent debate on what &func should 
 do (take
 the address of the function vs. the address of its result). 
 With the
 unsafe meaning out of the way, only the safe one is eligible.

Added a dedicated section to the DIP: http://goo.gl/xkIXb Andrei

As per your encouragement to me, I suggest using 'opAddress' instead of 'addressOf' to allow future compatibility with structs.
Feb 06 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 6 February 2013 at 22:33:57 UTC, Andrei 
Alexandrescu wrote:
 On 2/6/13 5:22 PM, Timon Gehr wrote:
 I see. Generally?
 Eg. this detects the escape and allocates as well?:

 S* foo() safe{
 S s;
 return &s;
 }

I think I'm starting to see what you're doing there :o).

I have to admit this was a big puzzling point to me as well.
Feb 06 2013
prev sibling next sibling parent "Rob T" <alanb ucora.com> writes:
On Wednesday, 6 February 2013 at 22:14:42 UTC, Andrei 
Alexandrescu wrote:
 On 2/6/13 5:05 PM, Timon Gehr wrote:
 On 02/06/2013 08:12 PM, Andrei Alexandrescu wrote:
 It would be more consistent with C++, but less so with the 
 notion of
 safety. I find it very consistent that all uses of 
 &expression are safe,
 and this is the kind of consistency Walter and I believe is 
 worth aiming
 for.

So you are saying this should compile?: struct S{ int x; int foo() safe{ return x; } } int delegate() safe foo() safe{ S s; return &s.foo; }

Yah, it should, and it also should detect the escape and allocate foo's frame on the heap. Andrei

I thought we wanted to minimize allocations, especially silent ones. In the quoted example, I'd rather the address taking be disallowed at compile time unless the programmer explicitly allocated S on the heap. --rt
Feb 06 2013
prev sibling next sibling parent "Rob T" <alanb ucora.com> writes:
On Thursday, 7 February 2013 at 05:37:44 UTC, Rob T wrote:
 On Wednesday, 6 February 2013 at 22:14:42 UTC, Andrei 
 Alexandrescu wrote:
 On 2/6/13 5:05 PM, Timon Gehr wrote:
 On 02/06/2013 08:12 PM, Andrei Alexandrescu wrote:
 It would be more consistent with C++, but less so with the 
 notion of
 safety. I find it very consistent that all uses of 
 &expression are safe,
 and this is the kind of consistency Walter and I believe is 
 worth aiming
 for.

So you are saying this should compile?: struct S{ int x; int foo() safe{ return x; } } int delegate() safe foo() safe{ S s; return &s.foo; }

Yah, it should, and it also should detect the escape and allocate foo's frame on the heap. Andrei

I thought we wanted to minimize allocations, especially silent ones. In the quoted example, I'd rather the address taking be disallowed at compile time unless the programmer explicitly allocated S on the heap. --rt

In other words safe should explicitly mean "I hereby verify that the code is safe" not "I will silently re-write your code in unknown ways to make it safe". PLEASE reconsider! --rt
Feb 06 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 05:43:24 UTC, Rob T wrote:
 In other words  safe should explicitly mean "I hereby verify 
 that the code is safe" not "I will silently re-write your code 
 in unknown ways to make it safe".

safe never meant that and Andrei never suggested that.
Feb 06 2013
prev sibling next sibling parent "Rob T" <alanb ucora.com> writes:
On Thursday, 7 February 2013 at 05:54:29 UTC, deadalnix wrote:
 On Thursday, 7 February 2013 at 05:43:24 UTC, Rob T wrote:
 In other words  safe should explicitly mean "I hereby verify 
 that the code is safe" not "I will silently re-write your code 
 in unknown ways to make it safe".

safe never meant that and Andrei never suggested that.

I must have misunderstood something. What did he mean by this? ------------
 So you are saying this should compile?:

 struct S{
 int x;
 int foo() safe{ return x; }
 }

 int delegate() safe foo() safe{
 S s;
 return &s.foo;
 }

Yah, it should, and it also should detect the escape and allocate foo's frame on the heap. Andrei ------------ What is being allocated on the heap? --rt
Feb 07 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 08:48:30 UTC, Rob T wrote:
 On Thursday, 7 February 2013 at 05:54:29 UTC, deadalnix wrote:
 On Thursday, 7 February 2013 at 05:43:24 UTC, Rob T wrote:
 In other words  safe should explicitly mean "I hereby verify 
 that the code is safe" not "I will silently re-write your 
 code in unknown ways to make it safe".

safe never meant that and Andrei never suggested that.

I must have misunderstood something. What did he mean by this? ------------
 So you are saying this should compile?:

 struct S{
 int x;
 int foo() safe{ return x; }
 }

 int delegate() safe foo() safe{
 S s;
 return &s.foo;
 }

Yah, it should, and it also should detect the escape and allocate foo's frame on the heap. Andrei ------------ What is being allocated on the heap?

The frame pointer is, and it isn't dependent of system or safe .
Feb 07 2013
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Wed, 06 Feb 2013 17:36:24 -0000, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:
 A good part of that is the recent debate on what &func should do (take  
 the address of the function vs. the address of its result). With the  
 unsafe meaning out of the way, only the safe one is eligible.

&X takes the address of X. If X is a symbol which represents an 'int' you get the address of the int itself, not the address of the int's value. If X is a symbol which represents a 'function' you should get the address of the function itself, not the address of that functions value (AKA the result). That seems the most logical thing to implement, to me. I think the confusion arises because ppl conflate the symbol/variable/thing and that thing's value. If we implement this we then have to ask how to get the address of the value. I reckon; if you want the address of the value of the function then call the function and take the address of that i.e. &func(). Here, brackets are not optional because they indicate the function is being called. Alternately if you don't like that, perhaps &*func. So, if func is "ref int func()" then this syntax makes it analogous to an int* e.g. int i = 5; int *p = &i; &p // takes the address of the variable 'p' &*p // takes the address of the variable 'i' int i = 5; ref int func() { return i; } &func // takes the address of func &*func // takes the address of i I prefer: &func() // takes the address of i because to me that is clearer and nicer looking. This seems the most logical thing to do, and seems the most flexible to me. If &func were to take the address of the value of func (result) then we'd need to invent a new syntax to take the address of func itself and why do that when we don't really need to. IMO. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Feb 07 2013
prev sibling parent "Rob T" <alanb ucora.com> writes:
On Thursday, 7 February 2013 at 09:21:38 UTC, deadalnix wrote:
 On Thursday, 7 February 2013 at 08:48:30 UTC, Rob T wrote:
 On Thursday, 7 February 2013 at 05:54:29 UTC, deadalnix wrote:
 On Thursday, 7 February 2013 at 05:43:24 UTC, Rob T wrote:
 In other words  safe should explicitly mean "I hereby verify 
 that the code is safe" not "I will silently re-write your 
 code in unknown ways to make it safe".

safe never meant that and Andrei never suggested that.

I must have misunderstood something. What did he mean by this? ------------
 So you are saying this should compile?:

 struct S{
 int x;
 int foo() safe{ return x; }
 }

 int delegate() safe foo() safe{
 S s;
 return &s.foo;
 }

Yah, it should, and it also should detect the escape and allocate foo's frame on the heap. Andrei ------------ What is being allocated on the heap?

The frame pointer is, and it isn't dependent of system or safe .

S* foo() safe{ S s; return &s; } In the above example, will s be silently allocated on the heap? --rt
Feb 07 2013
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 2:38 AM, Andrei Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25

Updated with a section dedicated to address taking: http://wiki.dlang.org/DIP25#Taking_address Andrei
Feb 06 2013
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 06 Feb 2013 02:38:17 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Probably it'll need a fair amount of tweaking. Anyhow it's in  
 destroyable form.

 http://wiki.dlang.org/DIP25

First reaction: It should be GUARANTEED that addressOf is a simple load of the underlying pointer that ref represents. That is, the library/compiler should be compelled not to call a specific function or otherwise execute anything but a simple load (if not already in a register). If that can't be implemented, this whole DIP falls apart. The reason being, that although we want to make it clear the intentions of the code (by using the knowingly unsafe addressOf and not &), we don't want to penalize code for doing so. The D compiler and library should be neutral on performance, even if it is overly nanny-ish when it comes to safety. -Steve
Feb 06 2013
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/6/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.
 http://wiki.dlang.org/DIP25

Originally I thought addressOf was only planned for safe functions, but for system too? This will likely break almost every library in existence. And interfacing with C will become severely handicapped. Btw, using pointers can actually lead to code which is clearer in its intention: void foo(int* x, int* y) { } void test(int x, int y) { foo(&x, &y); // we know foo might modify these parameters } Since we don't have "ref" at the call site, using ref parameters can lead to code which isn't immediately understood at the call site: void foo(ref int x, ref int y) { } void test(int x, int y) { foo(x, y); // can the parameters be modified? it's not clear from the call site } Also the DIP argues that addressOf solves the property issue w.r.t. return values. I've proposed we use an .addressOf property which only works on property functions, and I saw no arguments against it.
Feb 06 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 3:02 PM, Andrej Mitrovic wrote:
 On 2/6/13, Andrei Alexandrescu<SeeWebsiteForEmail erdani.org>  wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.
 http://wiki.dlang.org/DIP25

Originally I thought addressOf was only planned for safe functions, but for system too? This will likely break almost every library in existence. And interfacing with C will become severely handicapped.

That's a good point.
 Btw, using pointers can actually lead to code which is clearer in its
intention:

 void foo(int* x, int* y) { }
 void test(int x, int y)
 {
      foo(&x,&y);  // we know foo might modify these parameters
 }

 Since we don't have "ref" at the call site, using ref parameters can
 lead to code which isn't immediately understood at the call site:

 void foo(ref int x, ref int y) { }
 void test(int x, int y)
 {
      foo(x, y);  // can the parameters be modified? it's not clear from
 the call site
 }

I think there's no way to have it both ways. You'll have to get used to the new style and make it a requirement instead of a stylistic preference. Pointers are what they are, and they're not appropriate for code that offers guarantees. We could define a bunch of special rules for pointers in safe mode, but I think it's cleaner this way: ref is for safe code, if you want to mess with things use pointers.
 Also the DIP argues that addressOf solves the  property issue w.r.t.
 return values. I've proposed we use an .addressOf property which only
 works on  property functions, and I saw no arguments against it.

There aren't, but a library approach is better than a magic work, all other things being equal. Andrei
Feb 06 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/6/2013 4:23 PM, Andrej Mitrovic wrote:
 On 2/6/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 Pointers are what they are, and they're not appropriate for
 code that offers guarantees.

But we're talking about system here. I would probably be fine with these rules if they only applied to safe. I feel like someone is trying to put training wheels on my mountain bike.

One reason why safe is not the default.
Feb 06 2013
prev sibling next sibling parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Wednesday, 6 February 2013 at 07:38:17 UTC, Andrei 
Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in 
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

I'm not sure why it's trying to safe-up pointers. Disallowing the & operator on stack variables is going to cause code breakage of unprecedented proportions (probably biggest since strings where made immutable), I know I use it a LOT in my projects, particularly when interfacing with C libraries or making slices to stack memory. Also, shoving the burden of performance onto the GC for the common case seems like a particularly bad choice considering the current state of the art. Pointers are relatively rare in D; when users take the address of a local variable, it's for a good reason.
Feb 06 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/13 5:26 PM, Jakob Ovrum wrote:
 On Wednesday, 6 February 2013 at 07:38:17 UTC, Andrei Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

I'm not sure why it's trying to safe-up pointers. Disallowing the & operator on stack variables is going to cause code breakage of unprecedented proportions (probably biggest since strings where made immutable), I know I use it a LOT in my projects, particularly when interfacing with C libraries or making slices to stack memory. Also, shoving the burden of performance onto the GC for the common case seems like a particularly bad choice considering the current state of the art. Pointers are relatively rare in D; when users take the address of a local variable, it's for a good reason.

I think it stands to reason that we should pull back a little bit and only tighten that particular screw in safe code. Andrei
Feb 06 2013
prev sibling next sibling parent Robert <jfanatiker gmx.at> writes:
What happened to the scope storage class for parameters.

Wouldn't this solve the problems, with the simple rule that you are not
allowed to pass transient objects by reference if the parameter was not
declared with scope? And if I understood correctly, the compiler is
already capable of locally ensuring that the address does not escape (to
ensure the scope requirement), so we are all set?

Maybe even simpler, so that the approach also works with variadic
template functions: All ref/pointer parameters of a trusted/safe method
are automatically scope. 

For the addressOf method, I think it would be needed far too often.
Think about std.stdio.readf() for example. It would really be annoying.

Best regards, 

Robert

On Wed, 2013-02-06 at 02:38 -0500, Andrei Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in 
 destroyable form.
 
 http://wiki.dlang.org/DIP25
 
 
 Thanks,
 
 Andrei

Feb 06 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/6/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 Pointers are what they are, and they're not appropriate for
 code that offers guarantees.

But we're talking about system here. I would probably be fine with these rules if they only applied to safe. I feel like someone is trying to put training wheels on my mountain bike.
Feb 06 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 6 February 2013 at 07:38:17 UTC, Andrei 
Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in 
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

Seems like a good DIP overall. The limitation on address taking seriously impair the possibility of implementing property properly to emulate a field. It seems like a solvable problem, as scope can be explicited. But then, some address taking are back, and so the syntax problem around previous DIP isn't solved (But that is arguably a good thing as we should solve problems themselves, not symptoms).
Feb 06 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/6/2013 7:30 PM, deadalnix wrote:
 The limitation on address taking seriously impair the possibility of
 implementing  property properly to emulate a field.

Properties are always going to be subsets of fields. For example, property int foo() { return 3; } is never going to work with trying to get the address of 3. Trying to make it work would be a quixotic quest of dubious utility. I.e. I disagree that it is a serious impairment.
 It seems like a solvable problem, as scope can be explicited. But then, some
 address taking are back, and so the syntax problem around previous DIP isn't
 solved (But that is arguably a good thing as we should solve problems
 themselves, not symptoms).

The only time (now) that you can take the address of function return value is if that is a return by ref. So, if taking the address of a ref is disallowed, then the syntax is no longer ambiguous.
Feb 06 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/6/2013 10:13 PM, deadalnix wrote:
 It is a given that  properties can't 100M emulate field, but the goal should be
 to close he gap as much as possible.

Ok, why should "as much as possible" be the goal? There are other considerations - what merit should they have? For example, I consider having an easily understood mental model of how things work to be very important. Having the language doing mysterious heroic things under the hood trying to implement someone else's idea of human intuition impairs anyone's ability to understand a language.
 It doesn't change anything in many cases. Especially for template alias
 parameters.

Why? foo seems straightforward as a template alias parameter, meaning the function foo. Alias parameters do not take expressions as arguments - so the expression rules do not apply.
 It doesn't change the intrinsic complexity of the proposal that
 conflate a function (as first class object), its return value, and the useless
 C/C++ entity that is a function.

Removing an ambiguous case does reduce the intrinsic complexity.
Feb 06 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/7/2013 12:22 AM, deadalnix wrote:
 Ok, why should "as much as possible" be the goal? There are other
 considerations - what merit should they have?

answer to that question, please share.

The point is, there must always be a balance of competing interests. That's certainly true here.
 For example, I consider having an easily understood mental model of how things
 work to be very important. Having the language doing mysterious heroic things
 under the hood trying to implement someone else's idea of human intuition
 impairs anyone's ability to understand a language.

Ease come from 2 main things : - Fit the mental model that an user have in realted area (ie other programing languages) - Simplicity (which is very different from ease). The current proposal seems easy to you because it is close o YOUR mental model, working on D. But on a larger scale, it fails at both criteria mentioned above : it is different from what exists in any languages mentioned in this NG,

Does C# always allow taking the address of a getter's return value? I don't know, but I'd be surprised if it did.
 and a same identifier can refers to 3 different distinct (however related)
concepts.

It is not unusual for an identifier to mean different things in different constructs.
 DIP25 aim to solve the ref issue. Which is clearly useful. Conflating that goal
 with making previous DIP on function call is only going to export the mess in
 another area of the language.

 This is the very example of why simplicity in semantic is key.

Simplicity is great, but it does not always trump everything else. It's also possible for reasonable people to disagree on what is simple or intuitive.
 It doesn't change anything in many cases. Especially for template alias
 parameters.

Why? foo seems straightforward as a template alias parameter, meaning the function foo. Alias parameters do not take expressions as arguments - so the expression rules do not apply.

An alias template parameter bind to a symbol. A symbol can be either a first-class function

Yes.
 or a the other entity that have no name (the symbol resulting of a function
declaration).

Yes. But I don't see the issue. &foo cannot bind to an alias parameter, nor can foo().
 It doesn't change the intrinsic complexity of the proposal that
 conflate a function (as first class object), its return value, and the useless
 C/C++ entity that is a function.

Removing an ambiguous case does reduce the intrinsic complexity.

I'm sure that, as a developer that specialized itself in compilers, you perfectly know the difference between syntax and semantic. And that solving a syntax issue that is symptom of a semantic issue will not fix the semantic issue.

What &foo means is a semantic issue, not a syntactic one. It's not an ambiguous grammar. Semantic ambiguity issues are resolved by creating rules (which one may consider intuitive or arbitrary) and applying them, which is what we're doing here. There are several such ambiguities in D that are resolved by applying semantic disambiguation rules. This is done because although it makes the spec (and the compiler) more complex, it is actually simpler for the user. Saying that one cannot take the address of a return value solves the semantic ambiguity problem with &foo.
Feb 07 2013
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/7/2013 2:05 AM, deadalnix wrote:
 On Thursday, 7 February 2013 at 09:23:20 UTC, Walter Bright wrote:
 The point is, there must always be a balance of competing interests. That's
 certainly true here.


Try designing anything by using one overriding principle - you won't get a useful result. Designs are always tradeoffs, always.
 Does C# always allow taking the address of a getter's return value? I don't
 know, but I'd be surprised if it did.

C# don't have address of. It isn't a system language. Even if you consider the whole stuff without the address problem, the D way is different than C#'s.

It's a different language, with a different view of things. Direct comparisons between D and C# need to take that into account.
 The 'funny' things is that C#'s would cause syntax problem issue with address
of,
 where D does.

I don't understand this sentence.
 and a same identifier can refers to 3 different distinct (however related)
 concepts.

It is not unusual for an identifier to mean different things in different constructs.

this is a good thing.

How does one prove anything is a "good thing"?
 Simplicity is great, but it does not always trump everything else. It's also
 possible for reasonable people to disagree on what is simple or intuitive.

whatever you want, but each time I choose the complex path in my programmer life, I ended up with that kind of effect. You also seems to conflate simple and intuitive,

Not really, I said "simple OR intuitive" :-)
 Yes. But I don't see the issue. &foo cannot bind to an alias parameter, nor
 can foo().


Sure. But I'm lost at what your point is with that example.
 There are several such ambiguities in D that are resolved by applying semantic
 disambiguation rules. This is done because although it makes the spec (and the
 compiler) more complex, it is actually simpler for the user.


Given the vast variety and complexity of languages out there, for every example of A you can find, I can find examples of !A. It's not really useful, after all, if other languages got it all right, there's no point to D.
 This kind of thing always seems simple of some cases, but ends up creating a
 huge minefield of special case when you start to combine feature together. And
 this is something that most D users experiences.

I believe that Andrei's proposal resolves these.
 It result in users not using advanced D features (see HIGGS topic for instance,
 or many codebases on github in general) or user having trouble. It is often
 advised to stay away form advanced features of D for production quality stuff
 and I have to say I share the observation. Working on large codebase (well
large
 . . . for a personal project, but clearly ridiculous compared to many companies
 codebase : ~25 000LOC) using advanced features of D, I run in such troubles
 almost on a daily basis, and have developed some knowledge of area of the
 language I should not even try to go in.

This is exactly why we're going through this exercise with the properties.
Feb 07 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/7/2013 3:16 AM, deadalnix wrote:
 The 'funny' things is that C#'s would cause syntax problem issue with address
 of,
 where D does.

I don't understand this sentence.

In C#, foo.bar won't execute bar's method of foo. It will get what is called in D a delegate. foo.bar() execute that delegate. It remove the need for &foo.bar altogether, so with that mechanism in D, no problem with & operator. Scala does even one step further by executing the method, or not, depending on what is expected, proving that optional () are compatible with. Back to D, we have void function() foo; foo is declared as a function here.

No, that declares foo as a "pointer to function".
 Now you can pass several object to templates alias parameters, that will behave
 differently in slightly different subtle ways. For no real good reason.

They won't behave any differently than they would outside of being passed as aliases. I don't see a special problem added with alias parameters.
 I don't think it is, and looking at other languages choices, I'm not alone.

Given the vast variety and complexity of languages out there, for every example of A you can find, I can find examples of !A. It's not really useful, after all, if other languages got it all right, there's no point to D.

hard to find a !A if we exclude C and C++ (well and D, but it is kind of excluded if look for references). I don't pretend none exists, but it seems pretty hard to find one.

There are few languages in the systems programming category (languages that give one full access to pointers), so excluding C and C++ seems rather draconian.
 He does so by adding special cases. That is the problem with special cases,
they
 multiply themselves faster than rabbits.

Taking the address of a ref was already problematic.
Feb 07 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/7/2013 6:15 AM, Zach the Mystic wrote:
 Can you tell me if you consider my proposal with regard to making ref safe and
 complete simple and intuitive both for compiler and user, and if not, why? (I
 don't have an opinion about '&' yet.)

 http://forum.dlang.org/thread/ket199$2c27$1 digitalmars.com#post-bsgrtofehxfjmzkaedfr:40forum.dlang.org

I don't know if it's complete and safe. It's not something that can be determined with a quick read.
Feb 07 2013
prev sibling next sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Wed, 06 Feb 2013 02:38:17 -0500
schrieb Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:

 Probably it'll need a fair amount of tweaking. Anyhow it's in 
 destroyable form.
 
 http://wiki.dlang.org/DIP25
 
 
 Thanks,
 
 Andrei

At first I was skeptical about how this would work with binary operator overloads where you have a lot of ref returns. (Think vector * matrix.) But as it seems, only stack local variables underly new restrictions. So anything that operates only on 'this' stays valid code. I'd still like to see some actual code that will break, since its bad to rely on lack of imagination and contrived examples. As for the address taking, I hope it doesn't end up in being nannied to much by the language. Like in the case with printf, it could really piss people off that don't understand the reasoning behind it. Make the error message informative for that: "Potential escape of pointer to stack local" or similar. -- Marco
Feb 06 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/6/2013 8:16 PM, Marco Leise wrote:
 As for the address taking, I hope it doesn't end up in being
 nannied to much by the language. Like in the case with printf,
 it could really piss people off that don't understand the
 reasoning behind it. Make the error message informative for
 that: "Potential escape of pointer to stack local" or
 similar.

I think C++ missed an opportunity with reference types. All they are in C++ are just another way to express a pointer. They don't really offer any semantic improvement - you can even have null references. In D, we have an opportunity to define reference types as a kind of "safe" pointer type - where we can get much of the advantages of pointers without the potential for memory corruption.
Feb 06 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/7/13 1:34 AM, H. S. Teoh wrote:
 On Wed, Feb 06, 2013 at 10:09:48PM -0800, Walter Bright wrote:
 On 2/6/2013 8:16 PM, Marco Leise wrote:
 As for the address taking, I hope it doesn't end up in being
 nannied to much by the language. Like in the case with printf,
 it could really piss people off that don't understand the
 reasoning behind it. Make the error message informative for
 that: "Potential escape of pointer to stack local" or
 similar.

I think C++ missed an opportunity with reference types. All they are in C++ are just another way to express a pointer. They don't really offer any semantic improvement - you can even have null references. In D, we have an opportunity to define reference types as a kind of "safe" pointer type - where we can get much of the advantages of pointers without the potential for memory corruption.

D ref types are currently highly crippled because of the inability to declare ref variables, which mandates ugly workarounds. It should be a first-class type qualifier IMO. (Yes I know it's currently a *function* qualifier, not a type qualifier... which makes it all the more ugly.)

Unfortunately type qualifiers have very high complexity costs. I think it's very neat that we managed to keep ref the way it is. Yes, I, too, would like to have a ref variable sometimes, but overall I'm please with the way it's working (post DIP25 especially). Andrei
Feb 06 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 06:06:56 UTC, Walter Bright wrote:
 On 2/6/2013 7:30 PM, deadalnix wrote:
 The limitation on address taking seriously impair the 
 possibility of
 implementing  property properly to emulate a field.

Properties are always going to be subsets of fields. For example, property int foo() { return 3; } is never going to work with trying to get the address of 3. Trying to make it work would be a quixotic quest of dubious utility. I.e. I disagree that it is a serious impairment.

Obviously it is not going to work in that case. You'll find a huge difference between it will not work in case XXX and it is impossible to make it work. It is a given that properties can't 100M emulate field, but the goal should be to close he gap as much as possible.
 It seems like a solvable problem, as scope can be explicited. 
 But then, some
 address taking are back, and so the syntax problem around 
 previous DIP isn't
 solved (But that is arguably a good thing as we should solve 
 problems
 themselves, not symptoms).

The only time (now) that you can take the address of function return value is if that is a return by ref. So, if taking the address of a ref is disallowed, then the syntax is no longer ambiguous.

It doesn't change anything in many cases. Especially for template alias parameters. It doesn't change the intrinsic complexity of the proposal that conflate a function (as first class object), its return value, and the useless C/C++ entity that is a function.
Feb 06 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 06:13:44 UTC, deadalnix wrote:
 It doesn't change anything in many cases. Especially for 
 template alias parameters. It doesn't change the intrinsic 
 complexity of the proposal that conflate a function (as first 
 class object), its return value, and the useless C/C++ entity 
 that is a function.

Reformulating : it helps on the grammatical perspective, but the semantic is still broken.
Feb 06 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Feb 06, 2013 at 10:09:48PM -0800, Walter Bright wrote:
 On 2/6/2013 8:16 PM, Marco Leise wrote:
As for the address taking, I hope it doesn't end up in being
nannied to much by the language. Like in the case with printf,
it could really piss people off that don't understand the
reasoning behind it. Make the error message informative for
that: "Potential escape of pointer to stack local" or
similar.

I think C++ missed an opportunity with reference types. All they are in C++ are just another way to express a pointer. They don't really offer any semantic improvement - you can even have null references. In D, we have an opportunity to define reference types as a kind of "safe" pointer type - where we can get much of the advantages of pointers without the potential for memory corruption.

D ref types are currently highly crippled because of the inability to declare ref variables, which mandates ugly workarounds. It should be a first-class type qualifier IMO. (Yes I know it's currently a *function* qualifier, not a type qualifier... which makes it all the more ugly.) T -- Дерево держится корнями, а человек - друзьями.
Feb 06 2013
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
Am Wed, 06 Feb 2013 23:45:51 +0100
schrieb Robert <jfanatiker gmx.at>:

 What happened to the scope storage class for parameters.
 
 Wouldn't this solve the problems, with the simple rule that you are
 not allowed to pass transient objects by reference if the parameter
 was not declared with scope? And if I understood correctly, the
 compiler is already capable of locally ensuring that the address does
 not escape (to ensure the scope requirement), so we are all set?

This is an important question. How would this new proposal interact with scope parameters? Scope parameters could at least: * Allow some otherwise trusted code to be safe: --------- trusted bool parse1(ref double v) { // Use C's scanf return scanf("%f", addressOf(v)) == 1; // Fine } --------- can be safe if scanf parameters are scope parameters. Ditto for the parse2 example with addressOf. * Taking the address of a stack variable or a ref parameter could be allowed and safe as long as it's only passed as scope parameters. (All examples in "Taking address" could work if scanf were using scope parameters) IIRC the main problem with scope parameters was that escape analysis isn't implemented yet. http://d.puremagic.com/issues/show_bug.cgi?id=6931
Feb 06 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 07:41:57 UTC, Johannes Pfau wrote:
 Am Wed, 06 Feb 2013 23:45:51 +0100
 schrieb Robert <jfanatiker gmx.at>:

 What happened to the scope storage class for parameters.
 
 Wouldn't this solve the problems, with the simple rule that 
 you are
 not allowed to pass transient objects by reference if the 
 parameter
 was not declared with scope? And if I understood correctly, the
 compiler is already capable of locally ensuring that the 
 address does
 not escape (to ensure the scope requirement), so we are all 
 set?

This is an important question. How would this new proposal interact with scope parameters?

scope in not enough, as you can alias parameters (for instance swap).
Feb 07 2013
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
Am Wed, 06 Feb 2013 02:38:17 -0500
schrieb Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:

 Probably it'll need a fair amount of tweaking. Anyhow it's in 
 destroyable form.
 
 http://wiki.dlang.org/DIP25
 
 
 Thanks,
 
 Andrei

Regarding the questions about scope parameters and allowing & in system code, wouldn't it make sense to change the rules to the following: * Taking the address in system code is allowed. You can do everything with the returned address just as right now. * Taking the address in safe code is also allowed, but you can't do anything with it: You can't assign it to anything, can't return it and can't dereference it. ** Once full escape analysis and scope parameters are implemented, those rule will be relaxed a little and passing such pointers to some functions (e.g. as scope parameters) will be allowed in safe code. ** addressOf isn't necessary as you can take addresses in system code anyway This makes more sense than disallowing the & operator completely as we'd have to reintroduce it anyway once scope is implemented. This way we start with a strict, conservative way and relax the rules when the compiler can prove that the operations are really safe.
Feb 07 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 06:23:10 UTC, Walter Bright wrote:
 On 2/6/2013 10:13 PM, deadalnix wrote:
 It is a given that  properties can't 100M emulate field, but 
 the goal should be
 to close he gap as much as possible.

Ok, why should "as much as possible" be the goal? There are other considerations - what merit should they have?

I don't think anyone have interest to get back on that. If you have another answer to that question, please share.
 For example, I consider having an easily understood mental 
 model of how things work to be very important. Having the 
 language doing mysterious heroic things under the hood trying 
 to implement someone else's idea of human intuition impairs 
 anyone's ability to understand a language.

Ease come from 2 main things : - Fit the mental model that an user have in realted area (ie other programing languages) - Simplicity (which is very different from ease). The current proposal seems easy to you because it is close o YOUR mental model, working on D. But on a larger scale, it fails at both criteria mentioned above : it is different from what exists in any languages mentioned in this NG, and a same identifier can refers to 3 different distinct (however related) concepts. DIP25 aim to solve the ref issue. Which is clearly useful. Conflating that goal with making previous DIP on function call is only going to export the mess in another area of the language. This is the very example of why simplicity in semantic is key.
 It doesn't change anything in many cases. Especially for 
 template alias
 parameters.

Why? foo seems straightforward as a template alias parameter, meaning the function foo. Alias parameters do not take expressions as arguments - so the expression rules do not apply.

An alias template parameter bind to a symbol. A symbol can be either a first-class function or a the other entity that have no name (the symbol resulting of a function declaration).
 It doesn't change the intrinsic complexity of the proposal that
 conflate a function (as first class object), its return value, 
 and the useless
 C/C++ entity that is a function.

Removing an ambiguous case does reduce the intrinsic complexity.

I'm sure that, as a developer that specialized itself in compilers, you perfectly know the difference between syntax and semantic. And that solving a syntax issue that is symptom of a semantic issue will not fix the semantic issue.
Feb 07 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 09:23:20 UTC, Walter Bright wrote:
 The point is, there must always be a balance of competing 
 interests. That's certainly true here.

That is an assertion not an argument.
 Does C# always allow taking the address of a getter's return 
 value? I don't know, but I'd be surprised if it did.

C# don't have address of. It isn't a system language. Even if you consider the whole stuff without the address problem, the D way is different than C#'s. The 'funny' things is that C#'s would cause syntax problem issue with address of, where D does.
 and a same identifier can refers to 3 different distinct 
 (however related) concepts.

It is not unusual for an identifier to mean different things in different constructs.

Usually not when they resolve to the same symbol. And it has to be proven that this is a good thing.
 Simplicity is great, but it does not always trump everything 
 else. It's also possible for reasonable people to disagree on 
 what is simple or intuitive.

Here we have a more complex solution, and more problem with it. Conclude whatever you want, but each time I choose the complex path in my programmer life, I ended up with that kind of effect. You also seems to conflate simple and intuitive, which are really unrelated. Simplicity is mostly objective, when intuition is mostly subjective. Both combined usually lead to ease.
 Yes.

 or a the other entity that have no name (the symbol resulting 
 of a function declaration).

Yes. But I don't see the issue. &foo cannot bind to an alias parameter, nor can foo().

void function() foo can.
 What &foo means is a semantic issue, not a syntactic one. It's 
 not an ambiguous grammar. Semantic ambiguity issues are 
 resolved by creating rules (which one may consider intuitive or 
 arbitrary) and applying them, which is what we're doing here.

You should hear ambiguous as ambiguous for the parser here. This is possible to make any crazy insane syntax unambiguous for the parser.
 There are several such ambiguities in D that are resolved by 
 applying semantic disambiguation rules. This is done because 
 although it makes the spec (and the compiler) more complex, it 
 is actually simpler for the user.

I don't think it is, and looking at other languages choices, I'm not alone. This kind of thing always seems simple of some cases, but ends up creating a huge minefield of special case when you start to combine feature together. And this is something that most D users experiences. It result in users not using advanced D features (see HIGGS topic for instance, or many codebases on github in general) or user having trouble. It is often advised to stay away form advanced features of D for production quality stuff and I have to say I share the observation. Working on large codebase (well large . . . for a personal project, but clearly ridiculous compared to many companies codebase : ~25 000LOC) using advanced features of D, I run in such troubles almost on a daily basis, and have developed some knowledge of area of the language I should not even try to go in.
Feb 07 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 06:36:22 UTC, H. S. Teoh wrote:
 D ref types are currently highly crippled because of the 
 inability to
 declare ref variables, which mandates ugly workarounds. It 
 should be a
 first-class type qualifier IMO. (Yes I know it's currently a 
 *function*
 qualifier, not a type qualifier... which makes it all the more 
 ugly.)

My heart say yes, but my brain doesn't really any way to make that work :/
Feb 07 2013
prev sibling next sibling parent Robert <jfanatiker gmx.at> writes:
The solution to this problem has been posted already many times, simply
allow fields to be marked with  property too, having the compiler lower
it to a private field with trivial setter/getter method.

As I already mentioned, I don't really see the point of properties at
all, if they are not interchangeable with fields. We could as well use
setXXX/getXXX as in Java.

On Wed, 2013-02-06 at 22:06 -0800, Walter Bright wrote:
 Properties are always going to be subsets of fields. For example,
 
       property int foo() { return 3; }
 
 is never going to work with trying to get the address of 3. Trying to
 make it 
 work would be a quixotic quest of dubious utility. I.e. I disagree
 that it is a 
 serious impairment.

Feb 07 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 10:32:38 UTC, Walter Bright wrote:
 On 2/7/2013 2:05 AM, deadalnix wrote:
 On Thursday, 7 February 2013 at 09:23:20 UTC, Walter Bright 
 wrote:
 The point is, there must always be a balance of competing 
 interests. That's
 certainly true here.


Try designing anything by using one overriding principle - you won't get a useful result. Designs are always tradeoffs, always.

Ho yeah, I'm not arguing against that. But what is seen as conflicting goal often aren't.
 Does C# always allow taking the address of a getter's return 
 value? I don't
 know, but I'd be surprised if it did.

C# don't have address of. It isn't a system language. Even if you consider the whole stuff without the address problem, the D way is different than C#'s.

It's a different language, with a different view of things. Direct comparisons between D and C# need to take that into account.
 The 'funny' things is that C#'s would cause syntax problem 
 issue with address of,
 where D does.

I don't understand this sentence.

In C#, foo.bar won't execute bar's method of foo. It will get what is called in D a delegate. foo.bar() execute that delegate. It remove the need for &foo.bar altogether, so with that mechanism in D, no problem with & operator. Scala does even one step further by executing the method, or not, depending on what is expected, proving that optional () are compatible with. Back to D, we have void function() foo; foo is declared as a function here. However, void bar() {} will also be called a function, even if the entity represented by foo and bar are completely different. When you do foo = &bar, you get a pointer on foo's instruction. Here foo isn't a function in the D sense, but an Array of CPU instruction, or something like that. This entity, coming from C/C++ hasn't ANY useful usage except taking the address of to get a function. Wanting to keep that useless entity is the source of most trouble with the & syntax, and also on previous DIP (not that one).
 How does one prove anything is a "good thing"?

Proven may be strong, but you can't refute that some things are better than others.
 Yes. But I don't see the issue. &foo cannot bind to an alias 
 parameter, nor
 can foo().


Sure. But I'm lost at what your point is with that example.

Now you can pass several object to templates alias parameters, that will behave differently in slightly different subtle ways. For no real good reason.
 I don't think it is, and looking at other languages choices, 
 I'm not alone.

Given the vast variety and complexity of languages out there, for every example of A you can find, I can find examples of !A. It's not really useful, after all, if other languages got it all right, there's no point to D.

If A is the instruction pack entity type mentionned above, you'll find pretty hard to find a !A if we exclude C and C++ (well and D, but it is kind of excluded if look for references). I don't pretend none exists, but it seems pretty hard to find one. Because the idea is bad for everybody : it make the language more complex, harder to implement compiler/tooling for, can conflict with other features, and worse, have no benefice. This is a bad idea in all possible way. Actually so bad that even PHP don't implement it.
 This kind of thing always seems simple of some cases, but ends 
 up creating a
 huge minefield of special case when you start to combine 
 feature together. And
 this is something that most D users experiences.

I believe that Andrei's proposal resolves these.

He does so by adding special cases. That is the problem with special cases, they multiply themselves faster than rabbits.
 It result in users not using advanced D features (see HIGGS 
 topic for instance,
 or many codebases on github in general) or user having 
 trouble. It is often
 advised to stay away form advanced features of D for 
 production quality stuff
 and I have to say I share the observation. Working on large 
 codebase (well large
 . . . for a personal project, but clearly ridiculous compared 
 to many companies
 codebase : ~25 000LOC) using advanced features of D, I run in 
 such troubles
 almost on a daily basis, and have developed some knowledge of 
 area of the
 language I should not even try to go in.

This is exactly why we're going through this exercise with the properties.

It is clear that the property improvement proposed by Andrei is a great step forward. However, the &foo.bar that return the delegate when bar is a property is exactly the kind of stuff that are waiting to explode. Yes, this DIP remove the syntactic ambiguity (does this take the delegate or the address of the result ?) but that is barely it. I'd say that the fact that & have a meaning is way more problematic than the fact that it is not possible to take the resulting address.
Feb 07 2013
prev sibling next sibling parent "Zach the Mystic" <reachBUTMINUSTHISzach gOOGLYmail.com> writes:
On Thursday, 7 February 2013 at 09:23:20 UTC, Walter Bright wrote:
 DIP25 aim to solve the ref issue. Which is clearly useful. 
 Conflating that goal
 with making previous DIP on function call is only going to 
 export the mess in
 another area of the language.

 This is the very example of why simplicity in semantic is key.

Simplicity is great, but it does not always trump everything else. It's also possible for reasonable people to disagree on what is simple or intuitive.

Can you tell me if you consider my proposal with regard to making ref safe and complete simple and intuitive both for compiler and user, and if not, why? (I don't have an opinion about '&' yet.) http://forum.dlang.org/thread/ket199$2c27$1 digitalmars.com#post-bsgrtofehxfjmzkaedfr:40forum.dlang.org
Feb 07 2013
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 07 Feb 2013 01:06:34 -0500, Walter Bright  
<newshound2 digitalmars.com> wrote:

 The only time (now) that you can take the address of function return  
 value is if that is a return by ref. So, if taking the address of a ref  
 is disallowed, then the syntax is no longer ambiguous.

Thinking about this, I don't know that I like the idea of disallowing taking the address of ref. One major usage of taking the address of ref returns is the opIndex operator: int *ptr = &arr[0]; Or, more generally, the front property of a range: int *ptr = &arr.front; What I am concerned about is that this is not going to have the desired effect. Instead of grudgingly switching to a new style of coding, people will simply return pointers instead of ref. -Steve
Feb 07 2013
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
Am Thu, 07 Feb 2013 09:04:29 +0100
schrieb "deadalnix" <deadalnix gmail.com>:

 On Thursday, 7 February 2013 at 07:41:57 UTC, Johannes Pfau wrote:
 Am Wed, 06 Feb 2013 23:45:51 +0100
 schrieb Robert <jfanatiker gmx.at>:

 What happened to the scope storage class for parameters.
 
 Wouldn't this solve the problems, with the simple rule that 
 you are
 not allowed to pass transient objects by reference if the 
 parameter
 was not declared with scope? And if I understood correctly, the
 compiler is already capable of locally ensuring that the 
 address does
 not escape (to ensure the scope requirement), so we are all 
 set?

This is an important question. How would this new proposal interact with scope parameters?

scope in not enough, as you can alias parameters (for instance swap).

Can you give an example? I understand the scope is not enough to completely replace the rules in the proposal, but shouldn't it be legal to pass addresses of stack variables in safe code as a scope parameter? Could this cause issues as well?
Feb 07 2013
prev sibling next sibling parent "Zach the Mystic" <reachBUTMINUSTHISzach gOOGLYmail.com> writes:
On Thursday, 7 February 2013 at 19:49:27 UTC, Walter Bright wrote:
 On 2/7/2013 6:15 AM, Zach the Mystic wrote:
 Can you tell me if you consider my proposal with regard to 
 making ref safe and
 complete simple and intuitive both for compiler and user, and 
 if not, why? (I
 don't have an opinion about '&' yet.)

 http://forum.dlang.org/thread/ket199$2c27$1 digitalmars.com#post-bsgrtofehxfjmzkaedfr:40forum.dlang.org

I don't know if it's complete and safe. It's not something that can be determined with a quick read.

Okay. But at least that's a 'check' on simple and intuitive? As far as why I think it's safe, my investigation led me to conclude that the key question was, how do I know whether to treat the return value of a ref function which accept a ref as local or global? I pass a value into a mysterious box, how do I know whether what comes out the other end is related to what I passed in, or something completely different? All the cases DIP25 takes care of are the ones which can be known just by the peculiarities of the call and signature, but many cases just leave you in the dark. The only way the compiler can know for sure without help from the function signature is by dipping into the function's code to take a look, which seems like too high a price to pay. About a month ago Jonathan M Davis brought this up and pointed out that the PIMPL idiom occasionally banishes altogether that opportunity for the compiler. After a few tries, I realized that 'out' was actually still available to use for this purpose, which is either pure luck (possible) or a hidden byproduct of the fact that 1) it's a good keyword to begin with or 2) there's a secret truth to its interchangeability with 'ref' which applies to return values as well as to parameter tags.
Feb 07 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 14:43:38 UTC, Steven 
Schveighoffer wrote:
 On Thu, 07 Feb 2013 01:06:34 -0500, Walter Bright 
 <newshound2 digitalmars.com> wrote:

 The only time (now) that you can take the address of function 
 return value is if that is a return by ref. So, if taking the 
 address of a ref is disallowed, then the syntax is no longer 
 ambiguous.

Thinking about this, I don't know that I like the idea of disallowing taking the address of ref. One major usage of taking the address of ref returns is the opIndex operator: int *ptr = &arr[0]; Or, more generally, the front property of a range: int *ptr = &arr.front; What I am concerned about is that this is not going to have the desired effect. Instead of grudgingly switching to a new style of coding, people will simply return pointers instead of ref.

Exactly.
Feb 07 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 7 February 2013 at 19:57:50 UTC, Walter Bright wrote:
 On 2/7/2013 3:16 AM, deadalnix wrote:
 The 'funny' things is that C#'s would cause syntax problem 
 issue with address
 of,
 where D does.

I don't understand this sentence.

In C#, foo.bar won't execute bar's method of foo. It will get what is called in D a delegate. foo.bar() execute that delegate. It remove the need for &foo.bar altogether, so with that mechanism in D, no problem with & operator. Scala does even one step further by executing the method, or not, depending on what is expected, proving that optional () are compatible with. Back to D, we have void function() foo; foo is declared as a function here.

No, that declares foo as a "pointer to function".

That isn't what I read. It is clearly written void function() foo; And if in int a; a is an int and in int* b, b is a pointer on int, foo must be a function. The fact that this very entity type is called function pointer is C is irrelevant. The distinction between the 2 is a problem in the first place, as it create new entities with different behavior, for a benefice that is unclear to me.
 Now you can pass several object to templates alias parameters, 
 that will behave
 differently in slightly different subtle ways. For no real 
 good reason.

They won't behave any differently than they would outside of being passed as aliases. I don't see a special problem added with alias parameters.

Because the same syntax have different meanings, so suddenly, you have to special case everything. That is never done in practice, not even in phobos.
 If A is the instruction pack entity type mentionned above, 
 you'll find pretty
 hard to find a !A if we exclude C and C++ (well and D, but it 
 is kind of
 excluded if look for references). I don't pretend none exists, 
 but it seems
 pretty hard to find one.

There are few languages in the systems programming category (languages that give one full access to pointers), so excluding C and C++ seems rather draconian.

I don't see why this should be limited to system languages. This is about function and most languages have functions (and most modern languages have first class functions). Additionally, as show with scala or C#, the semantic of theses language often do not conflict with pointer access.
 He does so by adding special cases. That is the problem with 
 special cases, they
 multiply themselves faster than rabbits.

Taking the address of a ref was already problematic.

Yes indeed. I never argued against that.
Feb 07 2013
prev sibling next sibling parent reply Chad Joan <chadjoan gmail.com> writes:
On 02/06/2013 02:38 AM, Andrei Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

A single delegate (closure) can be used to defer both reads and writes on an arbitrary expression. This works on naked variables, references, pointers, properties, and probably a number of other things I haven't thought of yet. Here's the relevance to DIP25: closures already have well-defined escape semantics. The downside is that they probably allocate heap way too aggressively in the current implementation. The upshot is that they are always memory-safe. This makes optimization a quality-of-implementation issue: a sufficiently intelligent compiler should be able to remove many allocations for non-escaping closures. Perhaps ref parameters should be delegates under the hood instead of pointers? The longterm disadvantage I see with this is the extra pointer that must be passed/returned. I wonder how hard it would be for the compiler to instantiate specialized oldschool-pointer versions of functions with ref parameters whenever calls are made that do not require the guarantees that closures provide. A working demonstration is given below. Destroy! import std.traits; import std.stdio; struct Option(T) { bool hasValue = false; union { ubyte nope; T value; } this( T value ) { hasValue = true; this.value = value; } } Option!T none(T)() { Option!T result; return result; } /* For some reason we need to cast to this to make template deduction work on any functions it gets passed into. */ template DelegateRef(T) { alias T delegate(Option!T intake) DelegateRef; } template isDelegateRef(T) { static if ( isDelegate!T ) { alias ReturnType!T R; static if ( is( T == R delegate(Option!R) ) ) enum isDelegateRef = true; else enum isDelegateRef = false; } else enum isDelegateRef = false; } string accessor(string expr) { return `cast(DelegateRef!(typeof(`~expr~`))) (`~ `delegate typeof(`~expr~`)(Option!(typeof(`~expr~`)) intake) {`~ ` if ( intake.hasValue )`~ ` return (`~expr~` = intake.value);`~ ` else`~ ` return `~expr~`;`~ `})`; } // Function that accepts a reference. auto someFunc(Q)(Q qux) if ( isDelegateRef!Q ) { alias ReturnType!Q T; auto x = qux(none!T); x |= 0xF00D; qux(Option!T(x)); return qux(none!T); } struct MyStruct { private int m_q; property int q() { writefln("get q (%x)",m_q); return m_q; } property int q(int v) { writefln("set q (%x = %x)", m_q, v); return m_q = v; } } void testRef( ref int foo ) { assert(someFunc(mixin(accessor("foo"))) == 0xF00D); } void testPtr( int* foo ) { assert(someFunc(mixin(accessor("*foo"))) == 0xF00D); } void main() { int abc = 0; assert(someFunc(mixin(accessor("abc"))) == 0xF00D); assert(abc == 0xF00D); int foo = 0; testRef(foo); assert(foo == 0xF00D); int bar = 0; testPtr(&bar); assert(bar == 0xF00D); MyStruct s; s.q = 0; assert(someFunc(mixin(accessor("s.q"))) == 0xF00D); assert(s.q == 0xF00D); }
Feb 07 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 8 February 2013 at 06:28:54 UTC, Chad Joan wrote:
 On 02/06/2013 02:38 AM, Andrei Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.

 http://wiki.dlang.org/DIP25


 Thanks,

 Andrei

A single delegate (closure) can be used to defer both reads and writes on an arbitrary expression. This works on naked variables, references, pointers, properties, and probably a number of other things I haven't thought of yet. Here's the relevance to DIP25: closures already have well-defined escape semantics. The downside is that they probably allocate heap way too aggressively in the current implementation. The upshot is that they are always memory-safe. This makes optimization a quality-of-implementation issue: a sufficiently intelligent compiler should be able to remove many allocations for non-escaping closures. Perhaps ref parameters should be delegates under the hood instead of pointers? The longterm disadvantage I see with this is the extra pointer that must be passed/returned. I wonder how hard it would be for the compiler to instantiate specialized oldschool-pointer versions of functions with ref parameters whenever calls are made that do not require the guarantees that closures provide. A working demonstration is given below. Destroy!

The cost of passing a delegate is way higher than the cost of passing the extra pointer. Delegate cause an opaque function call so : - All registers that the callee is allowed to trash must be saved preventively (even if the callee don't trash them). - CPU cannot really use branch prediction. - The compiler must assume that the delegate call may have arbitrary side effects so have to commit everything to memory and then take everything back afterward. This prevent many instruction reordering, register promotions, dead read/write elimination, constant propagation and so on. Considering passing by ref is sometime done to fasten things, this defeat the whole point. Note that the operation above are not dying slow, but clearly not a good fit for ref.
 import std.traits;
 import std.stdio;

 struct Option(T)
 {
     bool hasValue = false;
     union
     {
         ubyte nope;
         T value;
     }

     this( T value )
     {
         hasValue = true;
         this.value = value;
     }
 }

 Option!T none(T)()
 {
     Option!T result;
     return result;
 }

 /* For some reason we need to cast to this to make template 
 deduction work on any functions it gets passed into. */
 template DelegateRef(T)
 {
     alias T delegate(Option!T intake) DelegateRef;
 }

 template isDelegateRef(T)
 {
     static if ( isDelegate!T )
     {
         alias ReturnType!T R;
         static if ( is( T == R delegate(Option!R) ) )
             enum isDelegateRef = true;
         else
             enum isDelegateRef = false;
     }
     else
         enum isDelegateRef = false;
 }

 string accessor(string expr)
 {
     return
         `cast(DelegateRef!(typeof(`~expr~`))) (`~
         `delegate typeof(`~expr~`)(Option!(typeof(`~expr~`)) 
 intake) {`~
         `    if ( intake.hasValue )`~
         `        return (`~expr~` = intake.value);`~
         `    else`~
         `        return `~expr~`;`~
         `})`;
 }

 // Function that accepts a reference.
 auto someFunc(Q)(Q qux) if ( isDelegateRef!Q )
 {
     alias ReturnType!Q T;
     auto x = qux(none!T);
     x |= 0xF00D;
     qux(Option!T(x));
     return qux(none!T);
 }

 struct MyStruct
 {
     private int m_q;

      property int q()
     {
         writefln("get q (%x)",m_q);
         return m_q;
     }

      property int q(int v)
     {
         writefln("set q (%x = %x)", m_q, v);
         return m_q = v;
     }
 }

 void testRef( ref int foo )
 {
     assert(someFunc(mixin(accessor("foo"))) == 0xF00D);
 }

 void testPtr( int* foo )
 {
     assert(someFunc(mixin(accessor("*foo"))) == 0xF00D);
 }

 void main()
 {
     int abc = 0;
     assert(someFunc(mixin(accessor("abc"))) == 0xF00D);
     assert(abc == 0xF00D);

     int foo = 0;
     testRef(foo);
     assert(foo == 0xF00D);

     int bar = 0;
     testPtr(&bar);
     assert(bar == 0xF00D);

     MyStruct s;
     s.q = 0;
     assert(someFunc(mixin(accessor("s.q"))) == 0xF00D);
     assert(s.q == 0xF00D);
 }

Feb 07 2013
parent Chad Joan <chadjoan gmail.com> writes:
On 02/08/2013 02:06 AM, deadalnix wrote:
 On Friday, 8 February 2013 at 06:28:54 UTC, Chad Joan wrote:
 Destroy!

The cost of passing a delegate is way higher than the cost of passing the extra pointer. Delegate cause an opaque function call so : - All registers that the callee is allowed to trash must be saved preventively (even if the callee don't trash them). - CPU cannot really use branch prediction. - The compiler must assume that the delegate call may have arbitrary side effects so have to commit everything to memory and then take everything back afterward. This prevent many instruction reordering, register promotions, dead read/write elimination, constant propagation and so on. Considering passing by ref is sometime done to fasten things, this defeat the whole point. Note that the operation above are not dying slow, but clearly not a good fit for ref.

Fair enough. I wonder if we can learn something from it though. It does seem to provide a conceptual model that's very desirable.
Feb 08 2013
prev sibling next sibling parent "Michael" <pr m1xa.com> writes:
Two more things:

Disable a read/write propa like int getSetSomeInteger(int).
int getSomeInteger() and void setSomeIntger(int) only allowed.

And disable default parameter for setter.
Feb 09 2013
prev sibling next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Wed, 06 Feb 2013 22:11:40 -0800
schrieb Walter Bright <newshound2 digitalmars.com>:

 On 2/6/2013 4:23 PM, Andrej Mitrovic wrote:
 On 2/6/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 Pointers are what they are, and they're not appropriate for
 code that offers guarantees.

But we're talking about system here. I would probably be fine with these rules if they only applied to safe. I feel like someone is trying to put training wheels on my mountain bike.

One reason why safe is not the default.

It would also be very very nice, if we could at least write "Hello, world!" in safe D. -- Marco
Feb 10 2013
prev sibling next sibling parent "Tove" <tove fransson.se> writes:
On Wednesday, 6 February 2013 at 21:40:00 UTC, Andrei 
Alexandrescu wrote:
 On 2/6/13 3:02 PM, Andrej Mitrovic wrote:
 Also the DIP argues that addressOf solves the  property issue 
 w.r.t.
 return values. I've proposed we use an .addressOf property 
 which only
 works on  property functions, and I saw no arguments against 
 it.

There aren't, but a library approach is better than a magic work, all other things being equal. Andrei

struct S { property int var(); property void var(int); } The .addressOf property gave me the idea of solving the getter/setter issue, by having two properties... var.getter var.setter maybe it could be added to your library approach though?
Feb 10 2013
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, February 06, 2013 02:38:17 Andrei Alexandrescu wrote:
 Probably it'll need a fair amount of tweaking. Anyhow it's in
 destroyable form.
 
 http://wiki.dlang.org/DIP25

Overall, the ref part seems good, but I'm highly skeptical of the part on addresses. The main point I'd raise about the ref portion is that module-level variables need to be grouped in with the static variables. You seem to have marked some module-level variables as scope in the examples, but static has no effect on module-level variables. As for the addresses, it seems very bizarre to create a function for doing what & does and then make & legal only in very restricted circumstances. Having a safeAddressOf for some set of restricted circumstances might make sense, but couldn't the compiler just detect that & was safe under those circumstances? If the compiler can determine that it's safe using the function, it should be possible for it to determine it without. And disallowing & even in system code is _way_ overkill. The compiler is already able to detect at least some unsafe cases (e.g. taking the address of a local variable), and it's incredibly common to need to do some of those when interacting with C code (e.g. taking the address of a local variable and passing it to a C function). If the problem is ambiguities between taking the address of a function and the address of its return value, then I'd think that it would be much cleaner to just create a __trait for getting the address of a function. It's needed far less than taking the address of a variable, and the difference between & and addressOf is just going to sow confusion. It definitely seems like overkill to me to introduce a function for doing what & already does just to deal with the difference between taking the address of a function and taking the address of its return value. So, I'm in favor of the changes to ref, but I definitely don't like what this DIP does with &. - Jonathan M Davis
Feb 11 2013