Jump to page: 1 25  
Page
Thread overview
Why can't we make reference variables?
Aug 29, 2012
Tommi
Aug 29, 2012
cal
Aug 29, 2012
Tommi
Aug 29, 2012
Nick Sabalausky
Aug 29, 2012
anonymous
Aug 29, 2012
Jonathan M Davis
Aug 29, 2012
Tommi
Aug 29, 2012
Jonathan M Davis
Aug 29, 2012
Nick Sabalausky
Aug 29, 2012
Jonathan M Davis
Aug 29, 2012
Marco Leise
Aug 30, 2012
bearophile
Aug 30, 2012
Tommi
Aug 30, 2012
Jonathan M Davis
Aug 31, 2012
Tommi
Aug 31, 2012
Tommi
Aug 31, 2012
Tommi
Aug 29, 2012
Jonathan M Davis
Aug 29, 2012
Tommi
Aug 29, 2012
Nick Sabalausky
Aug 29, 2012
Era Scarecrow
Aug 29, 2012
Era Scarecrow
Aug 29, 2012
Tommi
Aug 29, 2012
Era Scarecrow
Aug 29, 2012
Tommi
Aug 29, 2012
Era Scarecrow
Aug 29, 2012
Tommi
Aug 29, 2012
Era Scarecrow
Aug 29, 2012
Tommi
Aug 29, 2012
Tommi
Aug 30, 2012
Tommi
Aug 30, 2012
Mehrdad
Aug 30, 2012
Namespace
Aug 30, 2012
Namespace
Aug 30, 2012
Tommi
Aug 30, 2012
Namespace
Aug 29, 2012
Namespace
Aug 29, 2012
Mehrdad
Aug 29, 2012
Timon Gehr
Aug 29, 2012
Tommi
Aug 29, 2012
Mehrdad
Aug 29, 2012
Mehrdad
August 29, 2012
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
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
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
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
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
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
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
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
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
I think there's an (undocumented?) Ref class in some file (object_.d?)
« First   ‹ Prev
1 2 3 4 5