Passing a reference to a returned reference

Timoses timosesu at gmail.com
Fri Jul 6 15:37:25 UTC 2018


On Friday, 6 July 2018 at 15:14:01 UTC, Michael wrote:
> class Agent
> {
>     private
>     {
>         double[int] mDict;
>     }
>
>     // Setter: copy
>     void beliefs(ref double[int] dict)
>     {
>         import std.stdio : writeln;
>         writeln("Setter function.");
>         this.mDict = dict;
>     }
>
>     // Getter
>     auto ref beliefs()
>     {
>         return this.mDict;
>     }
> }
>
> class Operator
> {
>     static auto ref create()
>     {
>         double[int] dict;
>         dict[2] = 1.0;
>         dict[1] = 0.0;
>         return dict;
>     }
> }

Throw in a writeln statement in getter and be amazed : D

     class Agent
     {
         private
         {
             double[int] mDict;
         }

         // Setter: copy
         void beliefs(ref double[int] dict)
         {
             import std.stdio : writeln;
             writeln("Setter function.");
             this.mDict = dict;
         }

         // Getter
         auto ref beliefs()
         {
             writeln("getter");
             return this.mDict;
         }
     }

     class Operator
     {
         static auto ref create()
         {
             double[int] dict;
             dict[2] = 1.0;
             dict[1] = 0.0;
             return dict;
         }
     }

     unittest
     {
         import std.stdio : writeln;

         Agent a = new Agent();

         writeln("Statement 1");
         a.beliefs = Operator.create();
         writeln("Statement 2");
         assert(a.beliefs.keys.length == 2);

         writeln("Statement 3");
         writeln(a.beliefs);
     }

If you remove the ref then "Statement 1" will use the setter 
method. Otherwise it calls the "auto ref" function to get a 
reference of 'mDict' and assign it a value. Essentially

         // Getter
         auto ref beliefs()
         {
             return this.mDict;
         }

makes your "private" variable not private any more, since you are 
leaking a reference to it. So any program calling "a.beliefs" can 
get a reference to your private data and modify it.

My guess is that (if ref is removed from the setter) it serves as 
a @property function:
https://dlang.org/spec/function.html#property-functions
So this allows the function to work in a statement like:
a.beliefs = <Whatever>

And apparently it is prioritized over the "ref beliefs()" 
function.


I guess it is nicer to actually use the "setter" function, as it 
allows you to inspect what the private data will be assigned to 
and take appropriate measures, whereas with the "ref beliefs()" 
method the private data is open for any manipulation out of your 
control.


More information about the Digitalmars-d-learn mailing list