www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Is the address-of operator (&) really needed?

reply "Sandeep Datta" <datta.sandeep gmail.com> writes:
Hi,

I was going through some sample code online and came across the 
following code fragment...

	listenHttp(settings, &handleRequest); //Where handleRequest is a 
function

My question to you is (as the title says) is the address-of 
operator (&) really needed here? Wouldn't it be better to 
consider handleRequest to be a reference to the actual function? 
I think this will make the system consistent with the way 
variables work in D. IMO this will bring functions/delegates 
closer to being first class objects in D.

What do you think?

Regards,
Sandeep Datta.
May 31 2012
next sibling parent reply simendsjo <simendsjo gmail.com> writes:
On Thu, 31 May 2012 11:36:47 +0200, Sandeep Datta  
<datta.sandeep gmail.com> wrote:

 Hi,

 I was going through some sample code online and came across the  
 following code fragment...

 	listenHttp(settings, &handleRequest); //Where handleRequest is a  
 function

 My question to you is (as the title says) is the address-of operator (&)  
 really needed here? Wouldn't it be better to consider handleRequest to  
 be a reference to the actual function? I think this will make the system  
 consistent with the way variables work in D. IMO this will bring  
 functions/delegates closer to being first class objects in D.

 What do you think?
It might be because of historical reasons. A long time ago, D allowed calling functions without (), so what if handleRequest returns a function? Should the passed reference be handleRequest or handleRequest()? This issue is still valid for properties as they can be called without ().
May 31 2012
next sibling parent simendsjo <simendsjo gmail.com> writes:
On Thu, 31 May 2012 11:58:41 +0200, simendsjo <simendsjo gmail.com> wrote:

 A long time ago, D allowed calling functions without ()
Still does without using -property :)
May 31 2012
prev sibling parent "Sandeep Datta" <datta.sandeep gmail.com> writes:
On Thursday, 31 May 2012 at 09:58:42 UTC, simendsjo wrote:
 On Thu, 31 May 2012 11:36:47 +0200, Sandeep Datta 
 <datta.sandeep gmail.com> wrote:

 Hi,

 I was going through some sample code online and came across 
 the following code fragment...

 	listenHttp(settings, &handleRequest); //Where handleRequest 
 is a function

 My question to you is (as the title says) is the address-of 
 operator (&) really needed here? Wouldn't it be better to 
 consider handleRequest to be a reference to the actual 
 function? I think this will make the system consistent with 
 the way variables work in D. IMO this will bring 
 functions/delegates closer to being first class objects in D.

 What do you think?
It might be because of historical reasons. A long time ago, D allowed calling functions without (), so what if handleRequest returns a function? Should the passed reference be handleRequest or handleRequest()? This issue is still valid for properties as they can be called without ().
Thanks for the information! But I think we should use real properties when we need to do that and stop using functions as improvised properties. Please see my response to Dejan Lekic for my argument supporting this claim.
May 31 2012
prev sibling next sibling parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
On Thu, 31 May 2012 11:36:47 +0200, Sandeep Datta wrote:

 Hi,
 
 I was going through some sample code online and came across the
 following code fragment...
 
 	listenHttp(settings, &handleRequest); //Where handleRequest is a
 function
 
 My question to you is (as the title says) is the address-of operator (&)
 really needed here? Wouldn't it be better to consider handleRequest to
 be a reference to the actual function? I think this will make the system
 consistent with the way variables work in D. IMO this will bring
 functions/delegates closer to being first class objects in D.
 
 What do you think?
 
 Regards,
 Sandeep Datta.
It is needed. Consider this example: import std.stdio; /* float handleRequest() { return 1.0f; } */ int handleRequest() { return 200; } // handleRequest() function int main() { int function() fptr; //fptr = handleRequest; // will not work, because it is "understdood" as: // fptr = handleRequest(); fptr = &handleRequest; // This will work if we have only one handleRequest(); // If you uncomment the first one, you are in trouble int val = handleRequest; // calls handleRequest() actualy //listenHttp(settings, fptr); // no need for & because fptr is an object of "int function()" type writeln(val); // OUTPUT: 200 return 0; } // main function -- Dejan Lekic mailto:dejan.lekic(a)gmail.com http://dejan.lekic.org
May 31 2012
next sibling parent simendsjo <simendsjo gmail.com> writes:
On Thu, 31 May 2012 11:58:58 +0200, Dejan Lekic <dejan.lekic gmail.com>  
wrote:
   int function() fptr;
   //fptr = handleRequest; // will not work, because it is "understdood"
 as:
                           // fptr = handleRequest();
Only without -property
May 31 2012
prev sibling next sibling parent reply "Sandeep Datta" <datta.sandeep gmail.com> writes:
   //fptr = handleRequest; // will not work, because it is 
 "understdood"
 as:
                           // fptr = handleRequest();
But do we really need this feature? Typing () does not seem to be too much work besides we can use properties if we really need to drop the brackets. And given the fact that properties have well understood use cases (see http://msdn.microsoft.com/en-us/library/bzwdh01d(VS.71).aspx#cpconpropertyusa eguidelinesanchor1) I am not sure using functions as properties is such a good idea.
   fptr = &handleRequest;  // This will work if we have only one
 handleRequest();
                           // If you uncomment the first one, 
 you are in
 trouble
Can't we use auto-inferencing here to select the right method since fptr has the required type information?
May 31 2012
next sibling parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"Sandeep Datta" <datta.sandeep gmail.com> wrote in message 
news:voifmkyfwlslfpgipvlj forum.dlang.org...
   //fptr = handleRequest; // will not work, because it is "understdood"
 as:
                           // fptr = handleRequest();
But do we really need this feature? Typing () does not seem to be too much work besides we can use properties if we really need to drop the brackets. And given the fact that properties have well understood use cases (see http://msdn.microsoft.com/en-us/library/bzwdh01d(VS.71).aspx#cpconpropertyusa eguidelinesanchor1) I am not sure using functions as properties is such a good idea.
This has been a *HUGE* source of debate. It's D's own little "tabs vs spaces" war. Ultimately, the () is going to be required (unless the function is marked property, in which case it'll be required that you *don't* use the parens). And as has been said before, it already works this way if you give the -property switch to DMD (and this behavior is planned to become the default...someday). But the only reason any of this is happening at all is because of a specific ambiguity that was discovered with the old "empty parens are optional" approach.
May 31 2012
parent reply "Sandeep Datta" <datta.sandeep gmail.com> writes:
 But the only reason any of this is happening at all is
 because of a specific ambiguity that was discovered with the 
 old "empty
 parens are optional" approach.
Hmm interesting (esp since it works out in favor of what I wanted :) ) but TBH I do not have a problem with leaving the parens out if it does not meddle with the way I'd prefer to use the language. But it seems you can't have the cake and eat it too. Having said that, what is your opinion on dropping the ampersand? To me it looks antiquated and out of place especially since it conjures up images of unsafe pointers in C/C++.
May 31 2012
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 31 May 2012 07:45:54 -0400, Sandeep Datta  
<datta.sandeep gmail.com> wrote:

 But the only reason any of this is happening at all is
 because of a specific ambiguity that was discovered with the old "empty
 parens are optional" approach.
Hmm interesting (esp since it works out in favor of what I wanted :) ) but TBH I do not have a problem with leaving the parens out if it does not meddle with the way I'd prefer to use the language. But it seems you can't have the cake and eat it too. Having said that, what is your opinion on dropping the ampersand? To me it looks antiquated and out of place especially since it conjures up images of unsafe pointers in C/C++.
If we removed the requirement for the ampersand, along with requiring parentheses for non-property functions, code which expected to call the function without parentheses would silently compile, but not do what was intended. D aims to avoid making code silently switch behavior, so I don't think we can do this. -Steve
May 31 2012
parent reply "Sandeep Datta" <datta.sandeep gmail.com> writes:
 If we removed the requirement for the ampersand, along with 
 requiring parentheses for non-property functions, code which 
 expected to call the function without parentheses would 
 silently compile, but not do what was intended.
Consider this... float handleRequest() { return 1.0f; } float x = handleRequest; //compilation error or auto x = handleRequest; writefln("%f", x); //compilation error I think we'd get a compile time error for most cases without significant changes to the compiler. But the edge cases if any can probably be detected at compile time with modifications to the compiler. Here is an edge case (for reference)... writefln(x);// will now print the address of the function
May 31 2012
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 31 May 2012 08:27:17 -0400, Sandeep Datta  
<datta.sandeep gmail.com> wrote:

 If we removed the requirement for the ampersand, along with requiring  
 parentheses for non-property functions, code which expected to call the  
 function without parentheses would silently compile, but not do what  
 was intended.
Consider this... float handleRequest() { return 1.0f; } float x = handleRequest; //compilation error or auto x = handleRequest; writefln("%f", x); //compilation error
What about: handleRequest; -Steve
May 31 2012
next sibling parent "Sandeep Datta" <datta.sandeep gmail.com> writes:
 What about:

 handleRequest;

 -Steve
Yes I have considered that but that should be pretty easy to detect and flag for correction, isn't it? I mean the compiler already knows it is supposed to be a call to the handleRequest function (if it doesn't how will it generate code for it?) so it should just let the user know this syntax is not supported anymore.
May 31 2012
prev sibling parent "Lars T. Kyllingstad" <public kyllingen.net> writes:
On Thursday, 31 May 2012 at 12:29:21 UTC, Steven Schveighoffer 
wrote:
 On Thu, 31 May 2012 08:27:17 -0400, Sandeep Datta 
 <datta.sandeep gmail.com> wrote:

 If we removed the requirement for the ampersand, along with 
 requiring parentheses for non-property functions, code which 
 expected to call the function without parentheses would 
 silently compile, but not do what was intended.
Consider this... float handleRequest() { return 1.0f; } float x = handleRequest; //compilation error or auto x = handleRequest; writefln("%f", x); //compilation error
What about: handleRequest;
That doesn't compile now, if handleRequest is a function pointer (or any other variable): Error: var has no effect in expression (handleRequest) A much bigger problem is implicit conversions to bool, which are used everywhere: if (handleRequest) { ... } assert (handleRequest); Now, they test the result of handleRequest. After the proposed change they test the function pointer. If this change were to happen we'd need a loooong period between parentheses becoming mandatory for non-properties and dropping the & operator. We're talking years here. It's totally not worth it. -Lars
Jun 02 2012
prev sibling parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
On Thu, 31 May 2012 12:25:20 +0200, Sandeep Datta wrote:

   //fptr = handleRequest; // will not work, because it is
 "understdood"
 as:
                           // fptr = handleRequest();
But do we really need this feature? Typing () does not seem to be too much work besides we can use properties if we really need to drop the brackets. And given the fact that properties have well understood use cases (see http://msdn.microsoft.com/en-us/library/bzwdh01d
(VS.71).aspx#cpconpropertyusageguidelinesanchor1)
 I am not sure using functions as properties is such a good idea.
 
   fptr = &handleRequest;  // This will work if we have only one
 handleRequest();
                           // If you uncomment the first one,
 you are in
 trouble
Can't we use auto-inferencing here to select the right method since fptr has the required type information?
Nope, i specifically made this example because D makes no difference between two or more functions with different return types. -- Dejan Lekic mailto:dejan.lekic(a)gmail.com http://dejan.lekic.org
May 31 2012
parent "Sandeep Datta" <datta.sandeep gmail.com> writes:
 Nope, i specifically made this example because D makes no 
 difference
 between two or more functions with different return types.
Are you talking about co-variance? Could you please explain what you mean when you say D does not distinguish between return types (possibly by pointing to contexts in which this happens)? If yes then I think this a different case all together. In this case it seems picking the right function is doable, co-variance notwithstanding. Note I am not saying this can be done without making any changes to the compiler/language but whatever changes are required IMO will be small.
May 31 2012
prev sibling parent deadalnix <deadalnix gmail.com> writes:
Le 31/05/2012 11:58, Dejan Lekic a écrit :
 On Thu, 31 May 2012 11:36:47 +0200, Sandeep Datta wrote:

 Hi,

 I was going through some sample code online and came across the
 following code fragment...

 	listenHttp(settings,&handleRequest); //Where handleRequest is a
 function

 My question to you is (as the title says) is the address-of operator (&)
 really needed here? Wouldn't it be better to consider handleRequest to
 be a reference to the actual function? I think this will make the system
 consistent with the way variables work in D. IMO this will bring
 functions/delegates closer to being first class objects in D.

 What do you think?

 Regards,
 Sandeep Datta.
It is needed. Consider this example: import std.stdio; /* float handleRequest() { return 1.0f; } */ int handleRequest() { return 200; } // handleRequest() function int main() { int function() fptr; //fptr = handleRequest; // will not work, because it is "understdood" as: // fptr = handleRequest(); fptr =&handleRequest; // This will work if we have only one handleRequest(); // If you uncomment the first one, you are in trouble int val = handleRequest; // calls handleRequest() actualy //listenHttp(settings, fptr); // no need for& because fptr is an object of "int function()" type writeln(val); // OUTPUT: 200 return 0; } // main function
This behavior is planed to be deprecated. The & behavior should go as well I think.
Jun 01 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, May 31, 2012 11:36:47 Sandeep Datta wrote:
 Hi,
 
 I was going through some sample code online and came across the
 following code fragment...
 
 	listenHttp(settings, &handleRequest); //Where handleRequest is a
 function
 
 My question to you is (as the title says) is the address-of
 operator (&) really needed here? Wouldn't it be better to
 consider handleRequest to be a reference to the actual function?
 I think this will make the system consistent with the way
 variables work in D. IMO this will bring functions/delegates
 closer to being first class objects in D.
 
 What do you think?
1. It's needed so that you can call it when calling C code. 2. Just because ref is often better than a pointer doesn't mean that it's never valuable to be able to pass a pointer to a variable. 3. ref doesn't work with variadic templates very well. Take a look a std.getopt.getopt. It takes pointers, not refs, and there isn't a way to make it take refs. 4. & is useful for getting function pointers. There is _zero_ roason to get rid of & IMHO. - Jonathan M Davis
May 31 2012
next sibling parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
On Thu, 31 May 2012 08:40:51 -0700, Jonathan M Davis wrote:

 On Thursday, May 31, 2012 11:36:47 Sandeep Datta wrote:
 Hi,
 
 I was going through some sample code online and came across the
 following code fragment...
 
 	listenHttp(settings, &handleRequest); //Where handleRequest is a
 function
 
 My question to you is (as the title says) is the address-of operator
 (&) really needed here? Wouldn't it be better to consider handleRequest
 to be a reference to the actual function? I think this will make the
 system consistent with the way variables work in D. IMO this will bring
 functions/delegates closer to being first class objects in D.
 
 What do you think?
1. It's needed so that you can call it when calling C code. 2. Just because ref is often better than a pointer doesn't mean that it's never valuable to be able to pass a pointer to a variable. 3. ref doesn't work with variadic templates very well. Take a look a std.getopt.getopt. It takes pointers, not refs, and there isn't a way to make it take refs. 4. & is useful for getting function pointers. There is _zero_ roason to get rid of & IMHO. - Jonathan M Davis
+1 100% I would add that "fptr = &function;" makes it _clear_ what is going on there, otherwise I would have to go and find what "function" is... -- Dejan Lekic mailto:dejan.lekic(a)gmail.com http://dejan.lekic.org
Jun 01 2012
parent reply "Sandeep Datta" <datta.sandeep gmail.com> writes:
 I would add that "fptr = &function;" makes it _clear_ what is 
 going on
 there, otherwise I would have to go and find what "function" 
 is...
There are two contradictory issues at work here which need to be balanced with each other... 1. While writing code we expect the compiler to understand what we want to do without writing a lot of code. Compiler inference is a boon here. D has some features supporting this (like auto). 2. While reading code and while trying to reason about the program we want the program to be self documenting and simple. Often as is the case with natural languages some redundancy is required to accomplish this. This makes a language verbose and increases the difficulty / effort required for writing programs. static code analyzers etc) so IMHO we should design our languages Removing the ampersand is one small step in this direction. Though I agree upfront I have not mastered all the nuances of D to even know if this is possible at all at this point of time.
Jun 01 2012
next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Friday, 1 June 2012 at 17:07:57 UTC, Sandeep Datta wrote:
 1. While writing code we expect the compiler to understand what 
 we want to do without writing a lot of code.
& is not "a lot of code".
Jun 01 2012
prev sibling parent "foobar" <foo bar.com> writes:
On Friday, 1 June 2012 at 17:07:57 UTC, Sandeep Datta wrote:
 I would add that "fptr = &function;" makes it _clear_ what is 
 going on
 there, otherwise I would have to go and find what "function" 
 is...
There are two contradictory issues at work here which need to be balanced with each other... 1. While writing code we expect the compiler to understand what we want to do without writing a lot of code. Compiler inference is a boon here. D has some features supporting this (like auto). 2. While reading code and while trying to reason about the program we want the program to be self documenting and simple. Often as is the case with natural languages some redundancy is required to accomplish this. This makes a language verbose and increases the difficulty / effort required for writing programs. IDEs, static code analyzers etc) so IMHO we should design our Removing the ampersand is one small step in this direction. Though I agree upfront I have not mastered all the nuances of D to even know if this is possible at all at this point of time.
What actually happens is that we read code more often than writing it (orders of magnitude more) and we also read other people's code as well. Obviouisly we only write our own code. This raises nightmares of my time as a junior developer maintaining code written by some morrons that decided to name functions with 4-letter abbreviations without any form of documentation what so ever. While I'm sure the original code was very clever and made perfect sense to those original developers and those abreviations were trivially obvious to them, it certainly has no meaning whatsoever to a new guy 30 years later. So no, prefering ease of writing over ease of reading is a STUPID MORONIC WRONG idea. In fact, all those fancy modern tools such as IDEs help write more readable code by auto-completeing long function names, aleviating the need to used criptic abreviations for faster writing sake. /rant Regarding the specific issue of the & - I think that it's a little more consistent to not have it but given the technical issues raised by others it ain't worth it at this time.
Jun 02 2012
prev sibling parent reply "Sandeep Datta" <datta.sandeep gmail.com> writes:
 1. It's needed so that you can call it when calling C code.
Why can't we just use information from the C function signature to determine when an address needs to be passed? Why is manual intervention required here?
 2. Just because ref is often better than a pointer doesn't mean 
 that it's
 never valuable to be able to pass a pointer to a variable.
Passing a pointer may be useful but IMO we should restrict such things to the unsafe context.
 3. ref doesn't work with variadic templates very well. Take a 
 look a
 std.getopt.getopt. It takes pointers, not refs, and there isn't 
 a way to make
 it take refs.
Is it because getopt() is a C function? If it is see my reply to what you are saying, some explanation will be helpful.
 4. & is useful for getting function pointers.
What does the function name represent when not used with an ampersand? If it doesn't represent anything then I think the language can be changed to yield an address directly without an ampersand.
Jun 01 2012
next sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 06/01/12 19:19, Sandeep Datta wrote:
 1. It's needed so that you can call it when calling C code.
Why can't we just use information from the C function signature to determine when an address needs to be passed? Why is manual intervention required here?
 2. Just because ref is often better than a pointer doesn't mean that it's
 never valuable to be able to pass a pointer to a variable.
Passing a pointer may be useful but IMO we should restrict such things to the unsafe context.
 3. ref doesn't work with variadic templates very well. Take a look a
 std.getopt.getopt. It takes pointers, not refs, and there isn't a way to make
 it take refs.
Is it because getopt() is a C function? If it is see my reply to your point explanation will be helpful.
 4. & is useful for getting function pointers.
What does the function name represent when not used with an ampersand? If it doesn't represent anything then I think the language can be changed to yield an address directly without an ampersand.
import std.stdio; property f() { writeln("oops"); return 0; } void main() { auto p = f; } artur
Jun 01 2012
parent reply "Sandeep Datta" <datta.sandeep gmail.com> writes:
    import std.stdio;
     property f() { writeln("oops"); return 0; }
    void main() { auto p = f; }

 artur
I understand what you are trying to say but I hear parens will become mandatory soon. This may not be a problem then.
Jun 01 2012
parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 06/01/12 19:41, Sandeep Datta wrote:
    import std.stdio;
     property f() { writeln("oops"); return 0; }
    void main() { auto p = f; }

 artur
I understand what you are trying to say but I hear parens will become mandatory soon. This may not be a problem then.
No, it's the other way around - parens are accepted now, but shouldn't be. The whole point of properties is to behave as fields. import std.stdio; struct S { property int x() { return 42; } } void main() { S s; auto p1 = &s.x; writeln(p1); auto p2 = s.x; writeln(p2); }
 While writing code we expect the compiler to understand what we want to do
without writing a lot of code.
Do you really consider '&' to be "a lot of code"? D is not as compact as it could be, but '&' is not part of that problem. It is necessary to disambiguate and makes the code more readable by being explicit. artur
Jun 01 2012
next sibling parent "Sandeep Datta" <datta.sandeep gmail.com> writes:
On Friday, 1 June 2012 at 18:07:12 UTC, Artur Skawina wrote:
 On 06/01/12 19:41, Sandeep Datta wrote:
    import std.stdio;
     property f() { writeln("oops"); return 0; }
    void main() { auto p = f; }

 artur
I understand what you are trying to say but I hear parens will become mandatory soon. This may not be a problem then.
No, it's the other way around - parens are accepted now, but shouldn't be. The whole point of properties is to behave as fields.
Ok, I overlooked the property declaration. Sorry about that.
 While writing code we expect the compiler to understand what 
 we want to do without writing a lot of code.
Do you really consider '&' to be "a lot of code"?
Actually no I don't consider it to be a lot of code but I think it is an annoyance nevertheless...one which I can live with.
Jun 01 2012
prev sibling parent "Sandeep Datta" <datta.sandeep gmail.com> writes:
On Friday, 1 June 2012 at 18:07:12 UTC, Artur Skawina wrote:
 On 06/01/12 19:41, Sandeep Datta wrote:
    import std.stdio;
     property f() { writeln("oops"); return 0; }
    void main() { auto p = f; }

 artur
I understand what you are trying to say but I hear parens will become mandatory soon. This may not be a problem then.
No, it's the other way around - parens are accepted now, but shouldn't be. The whole point of properties is to behave as fields.
Ok, I overlooked the property declaration. Sorry about that.
 While writing code we expect the compiler to understand what 
 we want to do without writing a lot of code.
Do you really consider '&' to be "a lot of code"?
Actually no I don't consider it to be a lot of code but I think it is an annoyance nevertheless...one which I can live with.
Jun 01 2012
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, June 01, 2012 19:19:17 Sandeep Datta wrote:
 1. It's needed so that you can call it when calling C code.
Why can't we just use information from the C function signature to determine when an address needs to be passed? Why is manual intervention required here?
How about something like int myVar; cFunc(&myVar, 7); The C function takes a pointer, and I want to pass a local variable to it. & is the way to do that. Even if I would have used ref or out for such a function if it were a D function, it's a C function, so I can't do that.
 2. Just because ref is often better than a pointer doesn't mean
 that it's
 never valuable to be able to pass a pointer to a variable.
Passing a pointer may be useful but IMO we should restrict such things to the unsafe context.
If you don't want to use them, don't use them. But pointers _are_ part of safe because they _are_ safe. It's pointer arithmetic which isn't safe. AA's in returns a pointer. If you want to put something other than a class on the heap, you need a pointer. Pointers aren't going anywhere. And if you need a pointer to something which isn't a pointer, then you need &.
 3. ref doesn't work with variadic templates very well. Take a
 look a
 std.getopt.getopt. It takes pointers, not refs, and there isn't
 a way to make
 it take refs.
Is it because getopt() is a C function? If it is see my reply to what you are saying, some explanation will be helpful.
It's not a C function. It's a variadic template. It's instantiated with whatever types it's given. It's literally _impossible_ to use ref with that sort of function. So, if you want it to take the variable and write to it, you have to pass a pointer to it.
 4. & is useful for getting function pointers.
What does the function name represent when not used with an ampersand? If it doesn't represent anything then I think the language can be changed to yield an address directly without an ampersand.
That wouldn't work due to properties. Really, if you prefer to use ref over pointers, then use ref and don't use &. But & is useful and necessary for some circumstances and removing it would cripple us for little to no benefit. - Jonathan M Davis
Jun 01 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/31/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 2. Just because ref is often better than a pointer doesn't mean that it's
 never valuable to be able to pass a pointer to a variable.
5. And '&' documents code better at the call site. I personally refuse to use out/ref arguments because the call site makes it ambiguous whether an argument is passed by reference or not.
Jun 01 2012
next sibling parent "Sandeep Datta" <datta.sandeep gmail.com> writes:
On Friday, 1 June 2012 at 15:58:04 UTC, Andrej Mitrovic wrote:
 On 5/31/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 2. Just because ref is often better than a pointer doesn't 
 mean that it's
 never valuable to be able to pass a pointer to a variable.
5. And '&' documents code better at the call site. I personally refuse to use out/ref arguments because the call site makes it ambiguous whether an argument is passed by reference or not.
Please see http://forum.dlang.org/post/ycwrmmvnpdwkonjwogax forum.dlang.org
Jun 01 2012
prev sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Friday, 1 June 2012 at 15:58:04 UTC, Andrej Mitrovic wrote:
 On 5/31/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 2. Just because ref is often better than a pointer doesn't 
 mean that it's
 never valuable to be able to pass a pointer to a variable.
5. And '&' documents code better at the call site. I personally refuse to use out/ref arguments because the call site makes it ambiguous whether an argument is passed by reference or not.
As someone which used to breath Turbo Pascal and Delphi, I really Never got the point with C only developers insisting take the address on the call site. This is also one of the features I dislike in Go and should be taken by the compiler in the presence of ref/var/& parameters.
Jun 01 2012
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 06/01/12 22:03, Jonathan M Davis wrote:
 On Friday, June 01, 2012 21:48:01 Artur Skawina wrote:
 On 06/01/12 21:18, Jonathan M Davis wrote:
 3. ref doesn't work with variadic templates very well. Take a
 look a
 std.getopt.getopt. It takes pointers, not refs, and there isn't
 a way to make
 it take refs.
Is it because getopt() is a C function? If it is see my reply to what you are saying, some explanation will be helpful.
It's not a C function. It's a variadic template. It's instantiated with whatever types it's given. It's literally _impossible_ to use ref with that sort of function. So, if you want it to take the variable and write to it, you have to pass a pointer to it.
import std.stdio; void go(A...)(auto ref A a) { a[0] = 42; a[1].y--; } struct S { int y; } void main() { int x; S s; go(x, s); writeln(x, " ", s); }
auto ref is _completely_ different from ref. The compiler chooses whether to pass by ref or not with the idea that it will pick whatever is most efficient for that type, but it's implementation-dependent whether something will be passed by ref or not. And using ref is no solution, because then _all_ of the arguments must be lvalues. If you want a function to take an arbitrary set of arguments where some of them are passed by ref and others not, you _can't do it_. You have to use pointers instead, because the types of all of the parameters are inferred from the arguments, and nothing ever gets inferred as ref, because ref is not a type constructor.
I only used "auto ref" so that nobody would complain that it fails for non-lvalues. You can use just 'ref', and i'd agree that such an interface would be saner. However, if you know of a case where 'auto ref' behaves as you describe, file it as a bug. That's not how it's defined, and that is not how it could be sanely implemented. The sane definition is 'if it's an lvalue then it's a ref parameter'. And if you go and check http://dlang.org/template.html you will see it's defined exactly like that. Really, the compiler *cannot* decide by itself if something is passed by value or not, it would make this feature unusable. artur
Jun 01 2012
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 06/01/12 23:42, Jonathan M Davis wrote:
 On Friday, June 01, 2012 22:18:19 Artur Skawina wrote:
 auto ref is _completely_ different from ref. The compiler chooses whether
 to pass by ref or not with the idea that it will pick whatever is most
 efficient for that type, but it's implementation-dependent whether
 something will be passed by ref or not. And using ref is no solution,
 because then _all_ of the arguments must be lvalues. If you want a
 function to take an arbitrary set of arguments where some of them are
 passed by ref and others not, you _can't do it_. You have to use pointers
 instead, because the types of all of the parameters are inferred from the
 arguments, and nothing ever gets inferred as ref, because ref is not a
 type constructor.
I only used "auto ref" so that nobody would complain that it fails for non-lvalues. You can use just 'ref', and i'd agree that such an interface would be saner. However, if you know of a case where 'auto ref' behaves as you describe, file it as a bug. That's not how it's defined, and that is not how it could be sanely implemented. The sane definition is 'if it's an lvalue then it's a ref parameter'. And if you go and check http://dlang.org/template.html you will see it's defined exactly like that. Really, the compiler *cannot* decide by itself if something is passed by value or not, it would make this feature unusable.
As the feature was proposed, it was up to the compiler to decide whether something was passed by lvalue or rvalue, it was supposed to choose whichever was most efficient. If Walter made it more specific than that (as the docs would indicate), then he's defined it more thoroughly, for better or worse.
I've never had to use 'auto ref' and did not even bother to check that page before writing my first reply - that's how insane any other interpretation would be; it really cannot work any other way. (unless the arguments type has an attribute specifying ref or value semantics, but D does not have those yet)
 But tt doesn't really matter. getopt can't be implemented using auto ref 
 regardless of how defined it is what's ref and not. It uses compile-time 
 reflection to examine the arguments and determine what they're for. Even 
 passing a flag as an lvalue would then make it a ref, making it look like it 
 was supposed to be taking an argument rather than being the string for the 
 flag. By taking pointers, it's explicit, and it works. That won't work with 
I'm probably the last person anyone could suspect of having pointerphobia... :) And using explicit pointers instead of refs as part of an interface is a good thing, usually much better than (ab)using refs for this. That doesn't mean however that it cannot be done. So, what is the problem with this 'flag'? AFAICS (never looked at the getopt code) it always receives the arguments in pairs, where only the second value needs to be a lvalue. (getopt options can be skipped over, and can not appear in between). Where is the problem? The fact that option strings could be passed by ref is harmless. artur
Jun 01 2012
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Saturday, June 02, 2012 00:23:44 Artur Skawina wrote:
 I've never had to use 'auto ref' and did not even bother to check that page
 before writing my first reply - that's how insane any other interpretation
 would be; it really cannot work any other way. (unless the arguments type
 has an attribute specifying ref or value semantics, but D does not have
 those yet)
Since the whole purpose of introducing auto ref was to do more or less what const ref does in C++ and try and pass stuff efficiently without caring whether it was an lvalue or rvalue, I'm not sure that it matters much, though arguably, the fact that it doesn't automatically make it all const would make that less sane. Though honestly, given that auto ref can only work with templates, I'd argue that it's pretty much a failure as far as its mandate goes.
 But tt doesn't really matter. getopt can't be implemented using auto ref
 regardless of how defined it is what's ref and not. It uses compile-time
 reflection to examine the arguments and determine what they're for. Even
 passing a flag as an lvalue would then make it a ref, making it look like
 it was supposed to be taking an argument rather than being the string for
 the flag. By taking pointers, it's explicit, and it works. That won't
 work with
I'm probably the last person anyone could suspect of having pointerphobia... :) And using explicit pointers instead of refs as part of an interface is a good thing, usually much better than (ab)using refs for this.
I was paying enough attention to who I was responding to. The OP seems to be very against &.
 That doesn't
 mean however that it cannot be done. So, what is the problem with this
 'flag'? AFAICS (never looked at the getopt code) it always receives the
 arguments in pairs, where only the second value needs to be a lvalue.
 (getopt options can be skipped over, and can not appear in between). Where
 is the problem? The fact that option strings could be passed by ref is
 harmless.
If you specifically watch for the getopt options and compile-time reflection properly flags as that enum type and nothing else as that enum type (I'm not quite sure where that stands, given how enums can't always seem to decide whether they're enums or not), then it may be possible to make getopt work based purely on positioning (it's been a while since I looked at the code, so I don't know quite what it's doing). But it's impossible to make it work based on type. So, even if you can make getopt work, the general problem of not being able to use ref on some but not all of the arguments to a variadic templates remains. You'd have to add a way to the language to indicate that an argument should be passed by ref - which may not be a bad idea. It would only make sense with templates, since that's the only place that the type is in flux, but it might be worth having. getopt works just fine with pointers though. - Jonathan M Davis
Jun 01 2012