www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Ref local variables?

reply Ben Davis <entheh cantab.net> writes:
Hi,

Please excuse the cross-post with D.learn. People have been helpful 
there with workarounds, but I'm bringing it here in the hope that we can 
discuss a language enhancement.

So - could support for 'ref' local variables be added, or is there a 
reason not to? I want to write something like:

MapTile[] map;    // It's a struct

ref MapTile tile=map[y*w+x];
tile.id=something;
tile.isWall=true;
someFunctionThatTakesRefMapTile(tile);

Here are the alternatives I'm aware of:

- Pointers. I'm using these for now, but it means extra & and * 
operators sometimes, it makes 'ref' less tempting where it IS allowed 
since it's not consistent, and I got the impression that pointers are 
only encouraged when interfacing with C code, so I was surprised to find 
I needed them here. (Am I wrong about this last part?)

- 'with' - doesn't work because of the function call, and also because 
it would only support one tile at once, whereas I sometimes have a few. 
For example I might define 'below=map[(y+1)*w+x]' at the same time, and 
then I can write "if (below.id==CLEAR) {below=tile; tile.id=CLEAR;}".

- Class instead of struct - I don't want to do this since the array is 
quite big and the struct pretty small, and that would be a lot of extra 
overhead.

- Some kind of solution involving 'pretend to be a reference' types with 
difficult-to-read implmenetations and optimisation caveats, not worth 
the fuss compared to using pointers.

Incidentally, this code is already supported:
   int x,y; getValues(x,y);
   void getValues(ref int x, ref int y) ...
Yet it's not clear that x and y are passed by reference - whereas the 
currently unsupported case with local variables doesn't suffer from that 
readability issue, and indeed "below=tile" is much more readable than 
"map[(y+1)*w+x]=map[y*w+x]".

I'd also expect it's trivial in terms of code generation, as parameters 
and local variables are very similar.

So it strikes me as a no-brainer :)

Thanks,

Ben :)
Jan 10 2012
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Ben Davis" <entheh cantab.net> wrote in message 
news:jeinah$2pnj$1 digitalmars.com...
 Hi,

 Please excuse the cross-post with D.learn. People have been helpful there 
 with workarounds, but I'm bringing it here in the hope that we can discuss 
 a language enhancement.

 So - could support for 'ref' local variables be added, or is there a 
 reason not to? I want to write something like:

 MapTile[] map;    // It's a struct

 ref MapTile tile=map[y*w+x];
 tile.id=something;
 tile.isWall=true;
 someFunctionThatTakesRefMapTile(tile);
I *really* want the ability to do that sort of thing, although I think it should be an alias rather than a ref variable: MapTile[] map; // It's a struct alias map[y*w+x] tile; tile.id=something; tile.isWall=true; someFunctionThatTakesRefMapTile(tile);
Jan 10 2012
next sibling parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 10 Jan 2012 21:55:53 -0600, Nick Sabalausky <a a.a> wrote:

 "Ben Davis" <entheh cantab.net> wrote in message
 news:jeinah$2pnj$1 digitalmars.com...
 Hi,

 Please excuse the cross-post with D.learn. People have been helpful there
 with workarounds, but I'm bringing it here in the hope that we can discuss
 a language enhancement.

 So - could support for 'ref' local variables be added, or is there a
 reason not to? I want to write something like:

 MapTile[] map;    // It's a struct

 ref MapTile tile=map[y*w+x];
 tile.id=something;
 tile.isWall=true;
 someFunctionThatTakesRefMapTile(tile);
I *really* want the ability to do that sort of thing, although I think it should be an alias rather than a ref variable: MapTile[] map; // It's a struct alias map[y*w+x] tile; tile.id=something; tile.isWall=true; someFunctionThatTakesRefMapTile(tile);
Would making pointers implicitly convert to ref parameters suffice? i.e. make void foo(ref int x) { x++; } int x = 5; auto y = &x; foo(y); valid D code?
Jan 10 2012
parent reply Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
I think that would introduce a big potential for bugs. Can't give you
an example, but I have a hunch :-)

I think alias is better, since ref doesn't change its target and thus
need not be evaluated at run-time. In fact, I think alias should work
for any sort of expression. In this case one of D's mottos will be
"Too big? Alias it!".

On Wed, Jan 11, 2012 at 8:16 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 10 Jan 2012 21:55:53 -0600, Nick Sabalausky <a a.a> wrote:

 "Ben Davis" <entheh cantab.net> wrote in message
 news:jeinah$2pnj$1 digitalmars.com...
 Hi,

 Please excuse the cross-post with D.learn. People have been helpful the=
re
 with workarounds, but I'm bringing it here in the hope that we can
 discuss
 a language enhancement.

 So - could support for 'ref' local variables be added, or is there a
 reason not to? I want to write something like:

 MapTile[] map; =C2=A0 =C2=A0// It's a struct

 ref MapTile tile=3Dmap[y*w+x];
 tile.id=3Dsomething;
 tile.isWall=3Dtrue;
 someFunctionThatTakesRefMapTile(tile);
I *really* want the ability to do that sort of thing, although I think i=
t
 should be an alias rather than a ref variable:

 MapTile[] map; =C2=A0 =C2=A0// It's a struct

 alias map[y*w+x] tile;
 tile.id=3Dsomething;
 tile.isWall=3Dtrue;
 someFunctionThatTakesRefMapTile(tile);
Would making pointers implicitly convert to ref parameters suffice? i.e. make =C2=A0 =C2=A0void foo(ref int x) { x++; } =C2=A0 =C2=A0int x =3D 5; =C2=A0 =C2=A0auto y =3D &x; =C2=A0 =C2=A0foo(y); valid D code?
--=20 Bye, Gor Gyolchanyan.
Jan 11 2012
parent reply Ben Davis <entheh cantab.net> writes:
What about the semantics here?

alias MapTile tile=map[y*w+x];
x++;
tile.id=something;

Personally I'd find 'ref' more intuitive since it doesn't have that 
question. Not that I'd object to alias ALSO being supported.

I'm probably not actually going to change any of those variables in my 
case, so if I had to use alias, I'd just want to be sure that the common 
subexpression elimination can pick it up. (My case is actually 3D fwiw.)

Note that this is already supported (apologies if I've got the syntax 
slightly wrong):

foreach (i, ref tile; map) { ... }

That's a local variable too. It could have instead been defined such 
that "tile" is an alias for "map[i]", but that would be a little strange.

On 11/01/2012 08:18, Gor Gyolchanyan wrote:
 I think that would introduce a big potential for bugs. Can't give you
 an example, but I have a hunch :-)

 I think alias is better, since ref doesn't change its target and thus
 need not be evaluated at run-time. In fact, I think alias should work
 for any sort of expression. In this case one of D's mottos will be
 "Too big? Alias it!".

 On Wed, Jan 11, 2012 at 8:16 AM, Robert Jacques<sandford jhu.edu>  wrote:
 On Tue, 10 Jan 2012 21:55:53 -0600, Nick Sabalausky<a a.a>  wrote:

 "Ben Davis"<entheh cantab.net>  wrote in message
 news:jeinah$2pnj$1 digitalmars.com...
 Hi,

 Please excuse the cross-post with D.learn. People have been helpful there
 with workarounds, but I'm bringing it here in the hope that we can
 discuss
 a language enhancement.

 So - could support for 'ref' local variables be added, or is there a
 reason not to? I want to write something like:

 MapTile[] map;    // It's a struct

 ref MapTile tile=map[y*w+x];
 tile.id=something;
 tile.isWall=true;
 someFunctionThatTakesRefMapTile(tile);
I *really* want the ability to do that sort of thing, although I think it should be an alias rather than a ref variable: MapTile[] map; // It's a struct alias map[y*w+x] tile; tile.id=something; tile.isWall=true; someFunctionThatTakesRefMapTile(tile);
Would making pointers implicitly convert to ref parameters suffice? i.e. make void foo(ref int x) { x++; } int x = 5; auto y =&x; foo(y); valid D code?
Jan 11 2012
parent reply "Nick Sabalausky" <a a.a> writes:
"Ben Davis" <entheh cantab.net> wrote in message 
news:jejkdm$16un$1 digitalmars.com...
 Note that this is already supported (apologies if I've got the syntax 
 slightly wrong):

 foreach (i, ref tile; map) { ... }

 That's a local variable too. It could have instead been defined such that 
 "tile" is an alias for "map[i]", but that would be a little strange.
That's a very good point. Technically, foreach is implemented such that its body is a function and the "i, ref tile" is the parameter list. But I think that's beside the point.
Jan 11 2012
parent "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 11 Jan 2012 16:49:35 -0600, Nick Sabalausky <a a.a> wrote:

 "Ben Davis" <entheh cantab.net> wrote in message
 news:jejkdm$16un$1 digitalmars.com...
 Note that this is already supported (apologies if I've got the syntax
 slightly wrong):

 foreach (i, ref tile; map) { ... }

 That's a local variable too. It could have instead been defined such that
 "tile" is an alias for "map[i]", but that would be a little strange.
That's a very good point. Technically, foreach is implemented such that its body is a function and the "i, ref tile" is the parameter list. But I think that's beside the point.
Given that enabling foreach's syntax for general D functions, i.e. myLoop(i, ref tile; map) { ... } has been discussed several times in this newsgroup, the fact that "i, ref tile" is the parameter list of a delegate is not beside the point.
Jan 11 2012
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:jej186$78q$1 digitalmars.com...
 "Ben Davis" <entheh cantab.net> wrote in message 
 news:jeinah$2pnj$1 digitalmars.com...
 Hi,

 Please excuse the cross-post with D.learn. People have been helpful there 
 with workarounds, but I'm bringing it here in the hope that we can 
 discuss a language enhancement.

 So - could support for 'ref' local variables be added, or is there a 
 reason not to? I want to write something like:

 MapTile[] map;    // It's a struct

 ref MapTile tile=map[y*w+x];
 tile.id=something;
 tile.isWall=true;
 someFunctionThatTakesRefMapTile(tile);
I *really* want the ability to do that sort of thing, although I think it should be an alias rather than a ref variable: MapTile[] map; // It's a struct alias map[y*w+x] tile; tile.id=something; tile.isWall=true; someFunctionThatTakesRefMapTile(tile);
I'm wrong. Using alias would have totally different semantics from your example. We really should have both: ref MapTile tileRef=map[y*w+x]; alias map[y*w+x] tileAlias; assert(&tileAlias == &tileRef); x++; // tileAlias now points to the next element, tileRef is unchanged assert(&tileAlias == &tileRef + 1);
Jan 11 2012
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 10 Jan 2012 20:06:21 -0500, Ben Davis <entheh cantab.net> wrote:

 Hi,

 Please excuse the cross-post with D.learn. People have been helpful  
 there with workarounds, but I'm bringing it here in the hope that we can  
 discuss a language enhancement.

 So - could support for 'ref' local variables be added, or is there a  
 reason not to?
This has been requested in the past. In order to convince Walter, it is helpful to examine past failed arguments. Try a search on the newsgroups archive. You also have to show why it's better to do it via the language than via the library. I think Simen's solution in the D.learn thread is pretty compelling. -Steve
Jan 11 2012
parent reply "Marco Leise" <Marco.Leise gmx.de> writes:
Am 11.01.2012, 14:27 Uhr, schrieb Steven Schveighoffer  
<schveiguy yahoo.com>:

 On Tue, 10 Jan 2012 20:06:21 -0500, Ben Davis <entheh cantab.net> wrote:

 Hi,

 Please excuse the cross-post with D.learn. People have been helpful  
 there with workarounds, but I'm bringing it here in the hope that we  
 can discuss a language enhancement.

 So - could support for 'ref' local variables be added, or is there a  
 reason not to?
This has been requested in the past. In order to convince Walter, it is helpful to examine past failed arguments. Try a search on the newsgroups archive. You also have to show why it's better to do it via the language than via the library. I think Simen's solution in the D.learn thread is pretty compelling. -Steve
Sorry, but it sounds plain masochistic to import a module and then instantiate a template every time you want quick access to variable in non-trivially indexed array. All I want is a pointer to that element, but if possible avoid the pointer syntax. Here is another example: Row* rt_a = &row_types[n_row_types]; rt_a.pattern = pattern & MASK_HIGH_BIT; foreach (b, ref rt_b; row_types[0 .. n_row_types]) { if ((rt_a.pattern & rt_b.pattern) == 0) { rt_a.combinations ~= b; rt_b.combinations ~= n_row_types; } } ++n_row_types; Every solution proposed so far obfuscates and/or increases lines of code. I don't mind templates or alias this, I use them in other situations. Especially with the alias syntax (alias row_types[n_row_types] rt_a) I have the logical problem, that rt_a is just a macro, not the manifest pointer to the requested array slot. If I change n_row_types afterwards, rt_a changes. The other issue is that the OP has a more involved indexing scheme, that slows down the code if evaluated again and again. Local ref variables on the other hand (if it doesn't break the language) are a way to use pointers without pointer syntax. That precludes any form of pointer arithmetics and unsafe operations that are generally connected to the idea of pointers on these variables. Especially in safe code I would not want to resort to pointers, but write more in a Java style where everything is a reference. Again, the problem is the lack of a clean, concise syntax to declare references to structs (either returned from a function as ref or retrieved from an array). Or we just stick to pointers (that I manage to avoid everywhere else, but in this case). - Marco
Jan 11 2012
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 11 Jan 2012 15:12:36 -0500, Marco Leise <Marco.Leise gmx.de> wrote:

 Am 11.01.2012, 14:27 Uhr, schrieb Steven Schveighoffer  
 <schveiguy yahoo.com>:

 On Tue, 10 Jan 2012 20:06:21 -0500, Ben Davis <entheh cantab.net> wrote:

 Hi,

 Please excuse the cross-post with D.learn. People have been helpful  
 there with workarounds, but I'm bringing it here in the hope that we  
 can discuss a language enhancement.

 So - could support for 'ref' local variables be added, or is there a  
 reason not to?
This has been requested in the past. In order to convince Walter, it is helpful to examine past failed arguments. Try a search on the newsgroups archive. You also have to show why it's better to do it via the language than via the library. I think Simen's solution in the D.learn thread is pretty compelling. -Steve
Sorry, but it sounds plain masochistic to import a module and then instantiate a template every time you want quick access to variable in non-trivially indexed array.
I disagree, this doesn't look that bad: auto tile = refOf(map[y*w+x]); If you're saying that importing a module to do this is too much, I think you will have an uphill battle convincing Andrei/Walter. -Steve
Jan 11 2012
parent "Nick Sabalausky" <a a.a> writes:
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message 
news:op.v7xweevveav7ka localhost.localdomain...
 On Wed, 11 Jan 2012 15:12:36 -0500, Marco Leise <Marco.Leise gmx.de> 
 wrote:

 Am 11.01.2012, 14:27 Uhr, schrieb Steven Schveighoffer 
 <schveiguy yahoo.com>:

 On Tue, 10 Jan 2012 20:06:21 -0500, Ben Davis <entheh cantab.net> wrote:

 Hi,

 Please excuse the cross-post with D.learn. People have been helpful 
 there with workarounds, but I'm bringing it here in the hope that we 
 can discuss a language enhancement.

 So - could support for 'ref' local variables be added, or is there a 
 reason not to?
This has been requested in the past. In order to convince Walter, it is helpful to examine past failed arguments. Try a search on the newsgroups archive. You also have to show why it's better to do it via the language than via the library. I think Simen's solution in the D.learn thread is pretty compelling. -Steve
Sorry, but it sounds plain masochistic to import a module and then instantiate a template every time you want quick access to variable in non-trivially indexed array.
I disagree, this doesn't look that bad: auto tile = refOf(map[y*w+x]); If you're saying that importing a module to do this is too much, I think you will have an uphill battle convincing Andrei/Walter.
It falls squarely into the category of "removing unnecessary restrictions in the langauge", which Andrei at least has said he's interested in. We already have ref variables: You're just currently limited to only using them as params. This is just simply lifting that restriction. Just like how we lifted the restriction of imports only being usable at the top-level of the AST. Resorting to a library may allow the same feature, but it's *very* unorthogonal and messy, and for no real benefit. (Granted, I've never been a fan of obsessing over othogonality, but throwing it away for no benefit is no good either.)
Jan 11 2012
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, January 11, 2012 01:06:21 Ben Davis wrote:
 So - could support for 'ref' local variables be added, or is there a
 reason not to?
While I don't really care about having ref local variables (it's possible in C++, and I almost never use them there - const & is pretty much the only way that I use references in C++), I _am_ curious as to why we ended up with ref for function parameters and foreach variables but not local variables. My _guess_ would be because of how a large percentage of C++ users do what I do and only use references for const & parameters, but I don't know. I may have to go digging through the archives to see if an explanation was given anywhere. - Jonathan M Davis
Jan 11 2012