January 24, 2013
On 01/24/2013 08:52 AM, ParticlePeter wrote:

> This method here ( my first approach ) does return a reference to an
> object on the heap, right ?

Yes, but the caller does not get a reference.

> static ref Singleton instance() {
> if ( s is null )
> s = new Singleton( 0 ) ;
> return * s ;
> }
>
> so when I use it with:
> auto another_s = Singleton.instance ;
>
> Why is the s inside the struct and another_s not identical ?
> Afaik that is the purpose of the ref keyword ?

When you print the type of another_s you will see that it is not a ref, because unlike C++, D does not have local ref variables; it has pointers for that purpose.

import std.stdio;

ref int foo()
{
    return *new int;
}

void main()
{
    auto i = foo();
    writeln(typeid(i));
}

Prints 'int', not 'ref int'. So, i is a copy of the dynamically created int.

Ali

January 24, 2013
On Thursday, 24 January 2013 at 17:00:44 UTC, Ali Çehreli wrote:
> On 01/24/2013 08:52 AM, ParticlePeter wrote:
>
> > This method here ( my first approach ) does return a
> reference to an
> > object on the heap, right ?
>
> Yes, but the caller does not get a reference.

Actually the caller gets the reference (which is a pointer from low-level POV), but allocates on stack struct object, and then does copy from returned reference to that stack object.

> > static ref Singleton instance() {
> > if ( s is null )
> > s = new Singleton( 0 ) ;
> > return * s ;
> > }
> >
> > so when I use it with:
> > auto another_s = Singleton.instance ;
> >
> > Why is the s inside the struct and another_s not identical ?
> > Afaik that is the purpose of the ref keyword ?
>
> When you print the type of another_s you will see that it is not a ref, because unlike C++, D does not have local ref variables; it has pointers for that purpose.
>

Yes, that the point - D does not have references like C++. And I should thought about C++ influence on understanding D :)

> import std.stdio;
>
> ref int foo()
> {
>     return *new int;
> }
>
> void main()
> {
>     auto i = foo();
>     writeln(typeid(i));
> }
>
> Prints 'int', not 'ref int'. So, i is a copy of the dynamically created int.
>
> Ali

January 24, 2013
On 01/24/13 17:52, ParticlePeter wrote:
>> Yes, but this can be broken by:
>>
>> import core.stdc.stdio : printf;
>>
>> struct Singleton  {
>>
>> private :
>>         this( int a = 0 ) {} ;
>>         static Singleton * s ;
>>
>> public :
>>         @disable this() ;
>>         static Singleton* instance()  {
>>                 if ( s is null )
>>                         s = new Singleton(0) ;
>>                 return s ;
>>         }
>>
>>         int val = 0 ;
>> }
>>
>> void main()
>> {
>>         Singleton s = * Singleton.instance;
>>         printf( "%d\n", s.val ) ; //
>>         Singleton.instance.val = 2 ;
>>         printf( "%d\n", s.val ) ; //0
>> }
>>
>> Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.
> 
> O.k. good to know, I'll try to avoid this. But one thing is still not clear,
> This method here ( my first approach ) does return a reference to an object on the heap, right ?
> 
> static ref Singleton instance()  {
>     if ( s is null )
>         s = new Singleton( 0 ) ;
>     return * s ;
> }
> 
> so when I use it with:
> auto another_s = Singleton.instance ;
> 
> Why is the s inside the struct and another_s not identical ? Afaik that is the purpose of the ref keyword ?

There currently are no reference variables in D [1]; the only way to get a reference to something is via function arguments (including implicit method ones) and function returns. So assigning a ref-return means a copy.

You can workaround it like this:

struct Singleton  {
private:
    this( int a = 0 ) {} ;
    static Singleton* s ;

public:
    @disable this();
    @disable this(this);
    static instance() @property {
        static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias obj this; @disable this(this); }
        if ( s is null )
            s = new Singleton( 0 ) ;
        return Ref!(typeof(this))(s) ;
    }

    int val = 0 ;
}

though, that's not how I'd do it.

artur

[1] Classes don't count; they are a reference /types/.
January 24, 2013
On Thursday, 24 January 2013 at 17:00:44 UTC, Ali Çehreli wrote:
> On 01/24/2013 08:52 AM, ParticlePeter wrote:
>
> > This method here ( my first approach ) does return a
> reference to an
> > object on the heap, right ?
>
> Yes, but the caller does not get a reference.
>
> > static ref Singleton instance() {
> > if ( s is null )
> > s = new Singleton( 0 ) ;
> > return * s ;
> > }
> >
> > so when I use it with:
> > auto another_s = Singleton.instance ;
> >
> > Why is the s inside the struct and another_s not identical ?
> > Afaik that is the purpose of the ref keyword ?
>
> When you print the type of another_s you will see that it is not a ref, because unlike C++, D does not have local ref variables; it has pointers for that purpose.
>
> import std.stdio;
>
> ref int foo()
> {
>     return *new int;
> }
>
> void main()
> {
>     auto i = foo();
>     writeln(typeid(i));
> }
>
> Prints 'int', not 'ref int'. So, i is a copy of the dynamically created int.
>
> Ali

Thanks, I re-read the purpose of ref type function() in the D programming language, and the sole purpose is that such a function call can be directly a parameter to another function expecting a ref ? As:

ref int foo()  {  return some class member ;  }
void bar( ref int data )  {  do something with data ;  }

This means, it is never ever possible to initialize any variable with a reference some class/struct member data ? Unless I return the address of the member data ?


January 24, 2013
On 01/24/13 18:14, Artur Skawina wrote:
> struct Singleton  {
> private:
>     this( int a = 0 ) {} ;
>     static Singleton* s ;
> 
> public:
>     @disable this();
>     @disable this(this);
>     static instance() @property {
>         static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias obj this; @disable this(this); }
>         if ( s is null )
>             s = new Singleton( 0 ) ;
>         return Ref!(typeof(this))(s) ;
>     }
> 
>     int val = 0 ;
> }

Grr. What I meant to write was of course:

 static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias g this; @disable this(this); }

Sorry,

artur
January 24, 2013
On Thursday, 24 January 2013 at 17:21:38 UTC, Artur Skawina wrote:
> On 01/24/13 17:52, ParticlePeter wrote:
>>> Yes, but this can be broken by:
>>>
>>> import core.stdc.stdio : printf;
>>>
>>> struct Singleton  {
>>>
>>> private :
>>>         this( int a = 0 ) {} ;
>>>         static Singleton * s ;
>>>
>>> public :
>>>         @disable this() ;
>>>         static Singleton* instance()  {
>>>                 if ( s is null )
>>>                         s = new Singleton(0) ;
>>>                 return s ;
>>>         }
>>>
>>>         int val = 0 ;
>>> }
>>>
>>> void main()
>>> {
>>>         Singleton s = * Singleton.instance;
>>>         printf( "%d\n", s.val ) ; //
>>>         Singleton.instance.val = 2 ;
>>>         printf( "%d\n", s.val ) ; //0
>>> }
>>>
>>> Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.
>> 
>> O.k. good to know, I'll try to avoid this. But one thing is still not clear,
>> This method here ( my first approach ) does return a reference to an object on the heap, right ?
>> 
>> static ref Singleton instance()  {
>>     if ( s is null )
>>         s = new Singleton( 0 ) ;
>>     return * s ;
>> }
>> 
>> so when I use it with:
>> auto another_s = Singleton.instance ;
>> 
>> Why is the s inside the struct and another_s not identical ?
>> Afaik that is the purpose of the ref keyword ?
>
> There currently are no reference variables in D [1]; the only way to get
> a reference to something is via function arguments (including implicit
> method ones) and function returns. So assigning a ref-return means a copy.
>
> You can workaround it like this:
>
> struct Singleton  {
> private:
>     this( int a = 0 ) {} ;
>     static Singleton* s ;
>
> public:
>     @disable this();
>     @disable this(this);
>     static instance() @property {
>         static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias obj this; @disable this(this); }
>         if ( s is null )
>             s = new Singleton( 0 ) ;
>         return Ref!(typeof(this))(s) ;
>     }
> 
>     int val = 0 ;
> }
>
> though, that's not how I'd do it.
>
> artur
>
> [1] Classes don't count; they are a reference /types/.

Well ... I think I as well would not wanna do it like this, thanks :-)
I'm fine with returning and using a pointer, fortunately there is no difference in syntax as in c, so it doesn't matter.

January 24, 2013
On 01/24/2013 09:26 AM, ParticlePeter wrote:

> Thanks, I re-read the purpose of ref type function() in the D
> programming language, and the sole purpose is that such a function call
> can be directly a parameter to another function expecting a ref ?

As Maxim Fomin noted, I didn't word it correctly: The caller does get a reference to the returned object.

So, the sole purpose is not to pass a variable to a ref-taking function.

> As:
>
> ref int foo() { return some class member ; }
> void bar( ref int data ) { do something with data ; }
>
> This means, it is never ever possible to initialize any variable with a
> reference some class/struct member data ? Unless I return the address of
> the member data ?

Not true. There are no local ref variables nor ref member variables in D. All you need to do is to use pointers instead:

ref int foo()
{
    return *new int;
}

struct S
{
    int i;
    int * j;

    this(int i)
    {
        this.i = i;
        this.j = &foo();  // member pointer
    }
}

void main()
{
    int* i = &foo();  // local pointer
}

No, the pointer syntax is not the cleanest. :)

Ali

January 24, 2013
On 01/24/2013 09:35 AM, ParticlePeter wrote:

> I'm fine with returning and using a pointer, fortunately there is no
> difference in syntax as in c, so it doesn't matter.

With the exception that the -> operator is replaced by the dot operator in D:

    MyStruct * p = /* ... */;

    // Dot, not ->
    p.foo();
    p.i = 42;

Ali

January 24, 2013
On 01/24/13 18:35, ParticlePeter wrote:
> On Thursday, 24 January 2013 at 17:21:38 UTC, Artur Skawina wrote:
>> On 01/24/13 17:52, ParticlePeter wrote:
>>> Why is the s inside the struct and another_s not identical ? Afaik that is the purpose of the ref keyword ?
>>
>> There currently are no reference variables in D [1]; the only way to get a reference to something is via function arguments (including implicit method ones) and function returns. So assigning a ref-return means a copy.
>>
>> You can workaround it like this:
>>
>> struct Singleton  {
>> private:
>>     this( int a = 0 ) {} ;
>>     static Singleton* s ;
>>
>> public:
>>     @disable this();
>>     @disable this(this);
>>     static instance() @property {
>>         static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias g this; @disable this(this); }
>>         if ( s is null )
>>             s = new Singleton( 0 ) ;
>>         return Ref!(typeof(this))(s) ;
>>     }
>>
>>     int val = 0 ;
>> }

> Well ... I think I as well would not wanna do it like this, thanks :-)
> I'm fine with returning and using a pointer, fortunately there is no difference in syntax as in c, so it doesn't matter.

Careful, at some point you'll end up doing s[1] etc, and /then/ it matters. The Ref struct is actually the way to deal with "ref" types in D; what I meant by 'that's not how I'd do it' is that it might be better to use a global (well, thread-local module-field in D) etc.

artur
January 24, 2013
On Thursday, 24 January 2013 at 17:35:58 UTC, Ali Çehreli wrote:
> On 01/24/2013 09:26 AM, ParticlePeter wrote:
>
> > Thanks, I re-read the purpose of ref type function() in the D
> > programming language, and the sole purpose is that such a
> function call
> > can be directly a parameter to another function expecting a
> ref ?
>
> As Maxim Fomin noted, I didn't word it correctly: The caller does get a reference to the returned object.
>
> So, the sole purpose is not to pass a variable to a ref-taking function.
>
> > As:
> >
> > ref int foo() { return some class member ; }
> > void bar( ref int data ) { do something with data ; }
> >
> > This means, it is never ever possible to initialize any
> variable with a
> > reference some class/struct member data ? Unless I return the
> address of
> > the member data ?
>
> Not true. There are no local ref variables nor ref member variables in D. All you need to do is to use pointers instead:
>
> ref int foo()
> {
>     return *new int;
> }
>
> struct S
> {
>     int i;
>     int * j;
>
>     this(int i)
>     {
>         this.i = i;
>         this.j = &foo();  // member pointer
>     }
> }
>
> void main()
> {
>     int* i = &foo();  // local pointer
> }
>
> No, the pointer syntax is not the cleanest. :)
>
> Ali

This is what I meant :-) I can't return a reference ( with reference I don't mean reference type, but semantically a reference ) to a class member, but I can return the address of this member, which, to my understanding is an implicit pointer.

struct Foo  {
	int val = 3 ;
	auto getValPtr()  {  return & val ;  }
}

Foo foo ;
writeln( foo.val ) ; // = 3
auto valPtr = foo.getValPtr() ;
* valPtr  = 7 ;
writeln( foo.val ) ; // = 7