Thread overview | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 29, 2012 Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
In the following example code there's a situation, where the data we're looking for already exists, the data has value semantics, finding the data takes quite a lot of time, we need to "use" the data on multiple occasions, and the size of the data is so large that we don't want to copy it. In this situation, I think, the most convenient and sensible thing to do is to make a reference to the data, and use that reference multiple times. We could make a pointer, but then we'd be stuck with the nasty syntax of dereferencing: struct Book // has value semantics { // ... lots of data void read() const { // ... } } struct NationalLibrary { immutable Book[] _books; ref immutable(Book) find(string nameOfBook) { auto idx = 0; // ... takes quite long to figure out the index return _books[idx]; } } void main() { NationalLibrary nl; // This is fine if we just want to read it once: nl.find("WarAndPeace").read(); // ... but if we want to read it multiple times, we don't want // to each time go to the library and take the time to find it: immutable(Book)* ptrWarAndPeace = &nl.find("WarAndPeace"); // And now we're stuck with this syntax: (*ptrWarAndPeace).read(); (*ptrWarAndPeace).read(); // I'd like to be able to do this: // ref immutable(Book) refWarAndPeace = nl.find("WarAndPeace"); // refWarAndPeace.read(); // refWarAndPeace.read(); } Foreach loops can make reference variables, and function calls can do it for the parameters passed in. So, my question is, wouldn't it be better if we could, in general, make reference variables? |
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tommi | On Wednesday, 29 August 2012 at 00:21:29 UTC, Tommi wrote:
> In this situation, I think, the most convenient and sensible thing to do is to make a reference to the data, and use that reference multiple times. We could make a pointer, but then we'd be stuck with the nasty syntax of dereferencing:
This works currently:
struct Test
{
void foo() const
{
writeln("FOO");
}
}
void main()
{
immutable(Test)* ptr = new immutable(Test);
ptr.foo();
}
|
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to cal | On Wednesday, 29 August 2012 at 00:34:02 UTC, cal wrote:
> On Wednesday, 29 August 2012 at 00:21:29 UTC, Tommi wrote:
>> In this situation, I think, the most convenient and sensible thing to do is to make a reference to the data, and use that reference multiple times. We could make a pointer, but then we'd be stuck with the nasty syntax of dereferencing:
>
> This works currently:
>
> struct Test
> {
> void foo() const
> {
> writeln("FOO");
> }
> }
>
> void main()
> {
> immutable(Test)* ptr = new immutable(Test);
> ptr.foo();
> }
Now, that's a surprise for someone coming from C++. But even though ptr looks like a reference variable in your example, it doesn't look like it at all in this example:
void main()
{
int counter = 0;
auto notQuiteRefCounter = &counter;
// Increments the pointer, not counter value
++notQuiteRefCounter;
// Can't do this
// int counterBackup = notQuiteRefCounter;
// Prints deref: 0 no-deref: 18FD34
writefln("deref: %s no-deref: %s",
*notQuiteRefCounter,
notQuiteRefCounter);
}
|
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tommi | On Wednesday, August 29, 2012 02:21:28 Tommi wrote:
> Foreach loops can make reference variables, and function calls can do it for the parameters passed in. So, my question is, wouldn't it be better if we could, in general, make reference variables?
Not going to happen. Unfortunately though, I don't remember all of Walter's reasons for it, so I can't really say why (partly due to complications it causes in the language, I think, but I don't know). Use a pointer, std.typecons.RefCounted, a class, or make your struct a reference type (which would probably mean having the data held in a separate struct with a pointer to it in the outer struct). It's really not hard to have a type which is a reference type if that's what you really want. You just can't declare a ref to a variable as a local variable.
And really, the only two differences between using a pointer and being able to directly declare a reference like you can in C++ is the fact that a pointer can be null and that operations which don't use . require that you dereference the pointer first (e.g. ==). So, while there may be cases where being able to do something like
ref var = otherVar;
would be nice, it really doesn't buy you all that much.
- Jonathan M Davis
|
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tommi | Not exactly the same thing (what you propose would have different IFTI behaviour), but works quite well: import std.stdio; struct Ref(T){ private T* _payload; this(ref T i){_payload = &i; } @property ref T deref(){ return *_payload; } alias deref this; } auto ref_(T)(ref T arg){return Ref!T(arg);} void main(){ int i,j; auto r = i.ref_; r++; auto q = r; writeln(r," ",q); q++; writeln(r," ",q); q = j.ref_; q++; writeln(r," ",q.deref); } |
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Wednesday, 29 August 2012 at 01:28:49 UTC, Jonathan M Davis wrote:
> Not going to happen. Unfortunately though, I don't remember all of Walter's reasons for it, so I can't really say why (partly
> due to complications it causes in the language, I think, but I
> don't know).
I'd really like to hear about those complications (unless they're too complicated for me to understand), because for someone like me, not knowing the implementation details of the language, it looks like the language already *has* implemented reference variables. We just can't create them, apart from these few distinct ways:
foreach (ref actualRefVariable, array)
{
++actualRefVariable; // <-- that's a reference variable alright
}
void fun(ref int actualRefVariable)
{
++actualRefVariable; // <-- that's a reference variable alright
}
|
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Wednesday, 29 August 2012 at 01:42:36 UTC, Timon Gehr wrote:
> Not exactly the same thing (what you propose would have different
> IFTI behaviour), but works quite well:
>
> import std.stdio;
>
> struct Ref(T){
> private T* _payload;
> this(ref T i){_payload = &i; }
> @property ref T deref(){ return *_payload; }
> alias deref this;
> }
> auto ref_(T)(ref T arg){return Ref!T(arg);}
>
> void main(){
> int i,j;
> auto r = i.ref_;
> r++;
> auto q = r;
> writeln(r," ",q);
> q++;
> writeln(r," ",q);
> q = j.ref_;
> q++;
> writeln(r," ",q.deref);
> }
I did figure that that's possible. But, to me, having reference variables be implemented in a library instead of them being a core language feature, is like having pointers implemented as a library. I'd like to have a good answer when some newcomer asks me: "why, oh why is this so?".
|
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tommi | On Wed, 29 Aug 2012 03:16:20 +0200
"Tommi" <tommitissari@hotmail.com> wrote:
> On Wednesday, 29 August 2012 at 00:34:02 UTC, cal wrote:
> > On Wednesday, 29 August 2012 at 00:21:29 UTC, Tommi wrote:
> >> In this situation, I think, the most convenient and sensible thing to do is to make a reference to the data, and use that reference multiple times. We could make a pointer, but then we'd be stuck with the nasty syntax of dereferencing:
> >
> > This works currently:
> >
> > struct Test
> > {
> > void foo() const
> > {
> > writeln("FOO");
> > }
> > }
> >
> > void main()
> > {
> > immutable(Test)* ptr = new immutable(Test);
> > ptr.foo();
> > }
>
> Now, that's a surprise for someone coming from C++. But even though ptr looks like a reference variable in your example, it doesn't look like it at all in this example:
>
I've been primarily a D guy for years, and even I'm surprised by that! O_O
|
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tommi | On Wed, 29 Aug 2012 03:44:38 +0200
"Tommi" <tommitissari@hotmail.com> wrote:
> On Wednesday, 29 August 2012 at 01:28:49 UTC, Jonathan M Davis wrote:
> > Not going to happen. Unfortunately though, I don't remember all of Walter's reasons for it, so I can't really say why (partly due to complications it causes in the language, I think, but I don't know).
>
> I'd really like to hear about those complications (unless they're too complicated for me to understand),
I don't remember exactly either, but IIRC, it would somehow make it impossible to guarantee...something about references not escaping their proper scope...
|
August 29, 2012 Re: Why can't we make reference variables? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | I think there's an (undocumented?) Ref class in some file (object_.d?) |
Copyright © 1999-2021 by the D Language Foundation