Re: Ref local variables?

2012-01-09 Thread Steven Schveighoffer

On Sun, 08 Jan 2012 12:54:13 -0500, Ben Davis ent...@cantab.net wrote:


Hi,

Is there a reason 'ref' is disallowed for local variables? 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;

My actual case is more complicated, so inlining the expression  
everywhere would be messy. I can't use 'with' because I sometimes pass  
'tile' to a function (which also takes it as a ref). I don't want to  
make it a class since the array is quite big and that would be a lot of  
extra overhead. For now I'm using pointers, but this is forcing me to  
insert  or * operators sometimes, and it also reduces the temptation to  
use 'ref' in the places where it IS allowed, since it's inconsistent.


I hope it's not a stupid question - it's my first one - but I couldn't  
find an answer anywhere. I like most of what I've seen of D so far, and  
I'm very glad to be able to leave C and C++ (mostly) behind!


My first inclination is to use pointers.  D doesn't have - operator, so  
pointers are seamless for your small example:


auto tile = map[y*w+x];
tile.id = something;
tile.isWall = true;

When you need to pass it to a ref function, or if you do any operators on  
it, you would need to use *.


Another horribly inefficient option (if you don't use -inline) is this:

@property ref tile() { return map[y*w+x]; }

With new = syntax (in git head), this would probably be:

@property ref tile = map[y*w+x];

-Steve


Re: Ref local variables?

2012-01-09 Thread bearophile
Steven Schveighoffer:

 With new = syntax (in git head), this would probably be:
 
 @property ref tile = map[y*w+x];

That's not currently supported:
http://d.puremagic.com/issues/show_bug.cgi?id=7176

Bye,
bearophile


Re: Ref local variables?

2012-01-09 Thread Steven Schveighoffer
On Mon, 09 Jan 2012 09:27:06 -0500, bearophile bearophileh...@lycos.com  
wrote:



Steven Schveighoffer:


With new = syntax (in git head), this would probably be:

@property ref tile = map[y*w+x];


That's not currently supported:
http://d.puremagic.com/issues/show_bug.cgi?id=7176


The given function is not a method, but it is an inner-class function.

But you are right, it's a named function not a lambda.  I'm not too  
concerned about whether this version works or not, the other version is  
reasonably short.


I wonder if this would work, but it wouldn't be inlined like my original  
example:


auto tile = @property ref () = map[y*w+x];

-Steve


Ref local variables?

2012-01-08 Thread Ben Davis

Hi,

Is there a reason 'ref' is disallowed for local variables? 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;

My actual case is more complicated, so inlining the expression 
everywhere would be messy. I can't use 'with' because I sometimes pass 
'tile' to a function (which also takes it as a ref). I don't want to 
make it a class since the array is quite big and that would be a lot of 
extra overhead. For now I'm using pointers, but this is forcing me to 
insert  or * operators sometimes, and it also reduces the temptation to 
use 'ref' in the places where it IS allowed, since it's inconsistent.


I hope it's not a stupid question - it's my first one - but I couldn't 
find an answer anywhere. I like most of what I've seen of D so far, and 
I'm very glad to be able to leave C and C++ (mostly) behind!


Thanks,

Ben :)


Re: Ref local variables?

2012-01-08 Thread Trass3r

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

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


MapTile* tile = map[y*w+x];


Re: Ref local variables?

2012-01-08 Thread Trass3r

Sorry, didn't read the rest. ^^


Re: Ref local variables?

2012-01-08 Thread simendsjo

On 08.01.2012 18:54, Ben Davis wrote:

Hi,

Is there a reason 'ref' is disallowed for local variables? 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;

My actual case is more complicated, so inlining the expression
everywhere would be messy. I can't use 'with' because I sometimes pass
'tile' to a function (which also takes it as a ref). I don't want to
make it a class since the array is quite big and that would be a lot of
extra overhead. For now I'm using pointers, but this is forcing me to
insert  or * operators sometimes, and it also reduces the temptation to
use 'ref' in the places where it IS allowed, since it's inconsistent.

I hope it's not a stupid question - it's my first one - but I couldn't
find an answer anywhere. I like most of what I've seen of D so far, and
I'm very glad to be able to leave C and C++ (mostly) behind!

Thanks,

Ben :)


I got something working, but only when using templates. Take the 
following with a grain of salt as I'm a newbie myself.


struct MapTile {
string id;
}

enum w = 80, h = 25;
MapTile[w*h] map;

ref MapTile getTile(int x, int y) {
return map[y*w+x];
}

void f(T)(ref T tile) {
tile.id = f();
}

void g(ref MapTile tile) {
tile.id = g();
}

void main() {
// You can use auto ref return to set values directly
getTile(10,10).id = a;
assert(getTile(10,10).id == a);

// And using templated ref arguments, you can pass by reference
// note that I need to take the reference even when
// using auto ref return
auto tile = getTile(1,1);
f(tile);
assert(tile.id == f());

// But you'll need a dereference if not using a template
g(*tile);
assert(tile.id == g());

assert(getTile(1,1).id == g());
}



Re: Ref local variables?

2012-01-08 Thread Ben Davis

I also meant to say: 80x25? Epic :D

On 08/01/2012 20:25, Ben Davis wrote:

There are two things going on in your example:

1. Use of 'auto' where I'm currently having to write 'MapTile*' and
wanted to write 'ref MapTile'. It will infer 'MapTile*'. Or, if you
forget the , then it will infer 'MapTile' and do the copy that I want
to avoid. So it might be slightly more error-prone this way.

2. Use of a template function, allowing f() to take any type, not just
MapTile. Interestingly you're passing MapTile*, AND the parameter is
ref, so f() could change the pointer itself for the caller if it wanted
to! Also, if you called f() elsewhere with just a MapTile, you'd have
two copies if the function kicking around. So it saves us having to
write the *, but at the expense of some messiness. (Also prevents a lot
of the compile-time checks for f() from happening until f() is used.)

At least that's assuming D templates are like C++ ones. I haven't read
up on D templates yet. :)

So unfortunately, neither solution really solves the problem.

I suspect 'ref' for local variables could be added, and hasn't because
it didn't figure in the specific use cases that someone had in mind when
implementing it for parameters and 'foreach' variables. But it's also
possible that (unlike in Java) local variables can do stuff that
parameters can't (which I don't know about), which makes it impossible
to allow 'ref' ones without invalidating a compile-time check or
something. Hence why I was asking. :)

Anyway, I hope I've been able to help a bit with your own D adventure :)

Ben :)

On 08/01/2012 19:27, simendsjo wrote:

I got something working, but only when using templates. Take the
following with a grain of salt as I'm a newbie myself.

struct MapTile {
string id;
}

enum w = 80, h = 25;
MapTile[w*h] map;

ref MapTile getTile(int x, int y) {
return map[y*w+x];
}

void f(T)(ref T tile) {
tile.id = f();
}

void g(ref MapTile tile) {
tile.id = g();
}

void main() {
// You can use auto ref return to set values directly
getTile(10,10).id = a;
assert(getTile(10,10).id == a);

// And using templated ref arguments, you can pass by reference
// note that I need to take the reference even when
// using auto ref return
auto tile = getTile(1,1);
f(tile);
assert(tile.id == f());

// But you'll need a dereference if not using a template
g(*tile);
assert(tile.id == g());

assert(getTile(1,1).id == g());
}







Re: Ref local variables?

2012-01-08 Thread Ben Davis

There are two things going on in your example:

1. Use of 'auto' where I'm currently having to write 'MapTile*' and 
wanted to write 'ref MapTile'. It will infer 'MapTile*'. Or, if you 
forget the , then it will infer 'MapTile' and do the copy that I want 
to avoid. So it might be slightly more error-prone this way.


2. Use of a template function, allowing f() to take any type, not just 
MapTile. Interestingly you're passing MapTile*, AND the parameter is 
ref, so f() could change the pointer itself for the caller if it wanted 
to! Also, if you called f() elsewhere with just a MapTile, you'd have 
two copies if the function kicking around. So it saves us having to 
write the *, but at the expense of some messiness. (Also prevents a lot 
of the compile-time checks for f() from happening until f() is used.)


At least that's assuming D templates are like C++ ones. I haven't read 
up on D templates yet. :)


So unfortunately, neither solution really solves the problem.

I suspect 'ref' for local variables could be added, and hasn't because 
it didn't figure in the specific use cases that someone had in mind when 
implementing it for parameters and 'foreach' variables. But it's also 
possible that (unlike in Java) local variables can do stuff that 
parameters can't (which I don't know about), which makes it impossible 
to allow 'ref' ones without invalidating a compile-time check or 
something. Hence why I was asking. :)


Anyway, I hope I've been able to help a bit with your own D adventure :)

Ben :)

On 08/01/2012 19:27, simendsjo wrote:

I got something working, but only when using templates. Take the
following with a grain of salt as I'm a newbie myself.

struct MapTile {
string id;
}

enum w = 80, h = 25;
MapTile[w*h] map;

ref MapTile getTile(int x, int y) {
return map[y*w+x];
}

void f(T)(ref T tile) {
tile.id = f();
}

void g(ref MapTile tile) {
tile.id = g();
}

void main() {
// You can use auto ref return to set values directly
getTile(10,10).id = a;
assert(getTile(10,10).id == a);

// And using templated ref arguments, you can pass by reference
// note that I need to take the reference even when
// using auto ref return
auto tile = getTile(1,1);
f(tile);
assert(tile.id == f());

// But you'll need a dereference if not using a template
g(*tile);
assert(tile.id == g());

assert(getTile(1,1).id == g());
}





Re: Ref local variables?

2012-01-08 Thread Simen Kjærås

On Sun, 08 Jan 2012 18:54:13 +0100, Ben Davis ent...@cantab.net wrote:


Hi,

Is there a reason 'ref' is disallowed for local variables? 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;

My actual case is more complicated, so inlining the expression  
everywhere would be messy. I can't use 'with' because I sometimes pass  
'tile' to a function (which also takes it as a ref). I don't want to  
make it a class since the array is quite big and that would be a lot of  
extra overhead. For now I'm using pointers, but this is forcing me to  
insert  or * operators sometimes, and it also reduces the temptation to  
use 'ref' in the places where it IS allowed, since it's inconsistent.


I hope it's not a stupid question - it's my first one - but I couldn't  
find an answer anywhere. I like most of what I've seen of D so far, and  
I'm very glad to be able to leave C and C++ (mostly) behind!


Thanks,

Ben :)


Quick hack:

struct Ref( T ) {
private:
T* data;
public:
this( ref T value ) {
data = value;
}

ref inout(T) get( ) inout {
return *data;
}

alias get this;
}

Ref!T byRef( T )( ref T value ) {
return Ref!T( value );
}

unittest {
int a = 3;
Ref!int b = a;
b = 4;
assert( a == 4 );

auto c = byRef( a );
c = 5;
assert( a == 5 );
assert( b == 5 );
}