August 29, 2012
On Wednesday, 29 August 2012 at 02:28:09 UTC, Mehrdad wrote:
> I think there's an (undocumented?) Ref class in some file (object_.d?)

er, struct
August 29, 2012
On Wednesday, 29 August 2012 at 02:07:19 UTC, Nick Sabalausky wrote:
> 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

You didn't know that the dot operator does dereference? That's quite a big one to miss for years.
August 29, 2012
On Wednesday, 29 August 2012 at 01:28:49 UTC, Jonathan M Davis wrote:
> 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.

 You would need a flag added to EVERY variable and item to specify if it was stack allocated or not. Otherwise it would be quite annoying to deal with. The compiler has to work blindly, assuming everything is correct. You can ref what you've been given but making more permanent references aren't possible without bypassing the safeguards.

 Assuming 'ref' works:

 struct S {
   ref int r;
 }

 //ref local variable/stack, Ticking timebomb
 //compiler may refuse
 void useRef(ref S input, int r) {
   input.r = r;
 }

 //should be good, right?
 S useRef2(S input, ref int r) {  //Can declare @safe, right???
   input.r = r; //maybe, maybe not.
   return S;
 }

 //Shy should indirect care if it's local/stack or heap?
 S indirect(ref int r) {
   return useRef2(S(), r);
 }

 //local variables completely okay to ref! Right?
 S indirect2() {
   int r;
   return useRef2(S(), r);
 }

 S someScope() {
   int* pointer = new int(31); //i think that's right
   int local = 127;

   S s;

   //reference to calling stack! (which may be destroyed now);
   //Or worse it may silently work for a while
   useRef(s, 99);
   assert(s.r == 99);
   return s;

   s = useRef2(s, pointer); //or is it *pointer?
   assert(s.r == 31); //good so far if it passes correctly
   return s; //good, heap allocated

   s = useRef2(s, local);
   assert(s.r == 127); //good so far (still local)
   return s; //Ticking timebomb!

   s = indirect(local);
   assert(s.r == 127); //good so far (still local)
   return s; //timebomb!

   s = indirect2();
   return s; //already destroyed! Unknown consequences!
 }

 assuming a flag is silently passed to ensure if it is stack or heap allocated, then useRef2 silently becomes...

 //safe! But not C callable!
 S useRef2(S input, ref int r, bool __r_isHeap) {
   assert(__r_isHeap, "Cannot use a stack allocated variable!");
   input.r = r; //now @safe-able!
   return S;
 }

 Or at the end of the scope it could check all structs if the ref's had a silent flag specifying if a referenced variable was set for local, so it would assert/throw an exception at the end of the call.

 Am I wrong?
August 29, 2012
On Wednesday, 29 August 2012 at 02:57:27 UTC, Era Scarecrow wrote:
> You would need a flag added to EVERY variable and item to specify if it was stack allocated or not. Otherwise it would be quite annoying to deal with. The compiler has to work blindly, assuming everything is correct. You can ref what you've been given but making more permanent references aren't possible without bypassing the safeguards.

 To add on to this a little.. If you can only ref by calling, you ensure the variable is alive/valid when you are calling it regardless if it's stack or heap or global (But can't ensure it once the scope ends). Making a reference as a variable modifier won't work, but using a pointer you're already going lower level and it's all up to you the programmer to make sure it's right.

 I think that's right; Otherwise ref wouldn't be allowed in @safe code (at all).
August 29, 2012
On Wednesday, August 29, 2012 04:40:17 anonymous wrote:
> On Wednesday, 29 August 2012 at 02:07:19 UTC, Nick Sabalausky
> 
> wrote:
> > 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
> 
> You didn't know that the dot operator does dereference? That's quite a big one to miss for years.

Yeah. I'm a bit confused about what's so suprising about that code.

- Jonathan M Davis
August 29, 2012
On Wednesday, 29 August 2012 at 03:21:04 UTC, Jonathan M Davis wrote:
>> >> > 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
>> 
>> You didn't know that the dot operator does dereference? That's
>> quite a big one to miss for years.
>
> Yeah. I'm a bit confused about what's so suprising about that code.
>
> - Jonathan M Davis

The weird thing is that you can use a member access operator with a pointer (without explicitly dereferencing the pointer first). At least I didn't know what to expect the following code to print:

struct MyStruct
{
    int _value = 0;

    void increment()
    {
        ++_value;
    }
}

void increment(ref MyStruct* ptr)
{
    ++ptr;
}

void main()
{
    MyStruct[2] twoStructs;
    twoStructs[1]._value = 42;

    MyStruct* ptrFirstStruct = &twoStructs[0];

    // Are we incrementing the pointer using UFCS or
    // are we calling the member function in MyStruct?
    ptrFirstStruct.increment();

    // This prints 1, so we called the actual method
    writeln((*ptrFirstStruct)._value);
}
August 29, 2012
On Wednesday, 29 August 2012 at 03:17:39 UTC, Era Scarecrow wrote:
>  To add on to this a little.. If you can only ref by calling, you ensure the variable is alive/valid when you are calling it regardless if it's stack or heap or global (But can't ensure it once the scope ends). Making a reference as a variable modifier won't work, but using a pointer you're already going lower level and it's all up to you the programmer to make sure it's right.
>
>  I think that's right; Otherwise ref wouldn't be allowed in @safe code (at all).

But couldn't the compiler disallow all unsafe ref use in @safe code, and allow all use of ref in @system and @trusted code?
August 29, 2012
On Wednesday, August 29, 2012 06:46:25 Tommi wrote:
> The weird thing is that you can use a member access operator with a pointer (without explicitly dereferencing the pointer first).

Well, you clearly haven't done much pointers to structs in D, or that wouldn't be surprising at all. . always implicitly dereferences the pointer, which pretty much makes the -> operator completely unnecessary.

- Jonathan M Davis
August 29, 2012
On Tue, 28 Aug 2012 22:08:11 -0700
Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Wednesday, August 29, 2012 06:46:25 Tommi wrote:
> > The weird thing is that you can use a member access operator with a pointer (without explicitly dereferencing the pointer first).
> 
> Well, you clearly haven't done much pointers to structs in D,

I indeed haven't :) Usually "ref MyStruct" is good enough for my needs.

> or that
> wouldn't be surprising at all. . always implicitly dereferences the
> pointer, which pretty much makes the -> operator completely
> unnecessary.
> 

I always figured it was just the reference semantics for classes (and the optional "ref" when passing structs) that eliminated the need for ->.

Probably 99+% of the time I use structs it's either a plain-old-struct or "ref MyStruct", so I assumed C-style "(*foo).bar" was good enough for the rare uses of "MyStruct*", and it never bothered me.

But it's definitely pretty cool that dot still works even for pointers. It's awesome that D is still pleasantly surprising me :)

Out of curiosity, what about "MyStruct**" or "MyClass*"?

August 29, 2012
On Wednesday, August 29, 2012 02:04:44 Nick Sabalausky wrote:
> Out of curiosity, what about "MyStruct**" or "MyClass*"?

I'd have to try it, but my guess would be that it only implicitly dereferences
one level (though in the case of MyClass*, that might be enough, since there's
no dereferencing needed on class references - though it's _very_ rare that
having a pointer to a reference like that makes sense in the first place).

- Jonathan M Davis