www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can static variables in methods be local for each object?

reply Mark Lagodych <lgd.mrk gmail.com> writes:
Let's say I have this code:
```d
import std.stdio;

class X {

     int x(int param) {
         static int myvar = 1234;

         if (param == 0) return myvar;
         else { myvar = param; return myvar; }
     }

}

void main()
{
     X x1 = new X;
     X x2 = new X;

     x1.x(0).writeln;
     x2.x(0).writeln;

     x1.x(17).writeln;
     x2.x(0).writeln;
}
```

Is there a way to make myvar local to each instance of `X` 
without making it a variable of `X`? Just curious.
Jul 20 2021
next sibling parent Mark Lagodych <lgd.mrk gmail.com> writes:
On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:
 ```d
 void main()
 {
     X x1 = new X;
     X x2 = new X;

     x1.x(0).writeln;
     x2.x(0).writeln;

     x1.x(17).writeln;
     x2.x(0).writeln;
 }
 ```
Ow, sorry, I forgot to say. It prints: ``` 1234 1234 17 17 ```
Jul 20 2021
prev sibling next sibling parent bauss <jj_1337 live.dk> writes:
On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:
 Let's say I have this code:
 ```d
 import std.stdio;

 class X {

     int x(int param) {
         static int myvar = 1234;

         if (param == 0) return myvar;
         else { myvar = param; return myvar; }
     }

 }

 void main()
 {
     X x1 = new X;
     X x2 = new X;

     x1.x(0).writeln;
     x2.x(0).writeln;

     x1.x(17).writeln;
     x2.x(0).writeln;
 }
 ```

 Is there a way to make myvar local to each instance of `X` 
 without making it a variable of `X`? Just curious.
The only way I can think of is something like this: ``` import std.stdio; interface X { int x(int param); } class XImpl(size_t n = 0) : X { int x(int param) { static int myvar = 1234; if (param == 0) return myvar; else { myvar = param; return myvar; } } } void main() { X x1 = new XImpl!1; X x2 = new XImpl!2; x1.x(0).writeln; x2.x(0).writeln; x1.x(17).writeln; x2.x(0).writeln; } ``` Of course it's not entirely what you want but yeah I think that's about the closest to a solution that isn't overcomplicated.
Jul 20 2021
prev sibling next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:
 Is there a way to make myvar local to each instance of `X` 
 without making it a variable of `X`? Just curious.
Yes. ```d import std.stdio; class X { int x(int param) { static int[typeof(this)] myvar; if (param == 0) return myvar.get(this, 1234); else return myvar[this] = param; } } void main() { X x1 = new X; X x2 = new X; x1.x(0).writeln; //1234 x2.x(0).writeln; //1234 x1.x(17).writeln; //17 x2.x(0).writeln; //1234 x1.x(0).writeln; //17 x2.x(0).writeln; //1234 } ``` However, this is definitely not recommended. When you are calling a function with any particular object and argument set, you want it to do the same thing and return the same result, regardless of what's called before. Otherwise you're making debugging much more difficult than it needs to be. This means that `static` variables should generally be used only for two things: 1: data that is only set at the beginning of the program, or at first use, and then left to the initial value. 2: caching results of expensive computation. Even this is a bit controversal, as it's easy to screw up - often it's just better to split the function in two, and let the caller to cache the results. In this case, consider passing `myvar` explicitly: ```d import std.stdio; class X { int x(int param, ref int[typeof(this)] myvar) { if (param == 0) return myvar.get(this, 1234); else return myvar[this] = param; } } void main() { X x1 = new X; X x2 = new X; int[X] myvar; x1.x(17, myvar).writeln; //17 x2.x(0, myvar).writeln; //1234 x1.x(0, myvar).writeln; //17 x2.x(0, myvar).writeln; //1234 myvar = null; //Forget all calls made so far x1.x(0, myvar).writeln; //1234 x2.x(0, myvar).writeln; //1234 } ```
Jul 20 2021
parent bauss <jj_1337 live.dk> writes:
On Tuesday, 20 July 2021 at 15:59:30 UTC, Dukc wrote:
 On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:
 Is there a way to make myvar local to each instance of `X` 
 without making it a variable of `X`? Just curious.
Yes. ```d import std.stdio; class X { int x(int param) { static int[typeof(this)] myvar; if (param == 0) return myvar.get(this, 1234); else return myvar[this] = param; } } void main() { X x1 = new X; X x2 = new X; x1.x(0).writeln; //1234 x2.x(0).writeln; //1234 x1.x(17).writeln; //17 x2.x(0).writeln; //1234 x1.x(0).writeln; //17 x2.x(0).writeln; //1234 } ``` However, this is definitely not recommended. When you are calling a function with any particular object and argument set, you want it to do the same thing and return the same result, regardless of what's called before. Otherwise you're making debugging much more difficult than it needs to be. This means that `static` variables should generally be used only for two things: 1: data that is only set at the beginning of the program, or at first use, and then left to the initial value. 2: caching results of expensive computation. Even this is a bit controversal, as it's easy to screw up - often it's just better to split the function in two, and let the caller to cache the results. In this case, consider passing `myvar` explicitly: ```d import std.stdio; class X { int x(int param, ref int[typeof(this)] myvar) { if (param == 0) return myvar.get(this, 1234); else return myvar[this] = param; } } void main() { X x1 = new X; X x2 = new X; int[X] myvar; x1.x(17, myvar).writeln; //17 x2.x(0, myvar).writeln; //1234 x1.x(0, myvar).writeln; //17 x2.x(0, myvar).writeln; //1234 myvar = null; //Forget all calls made so far x1.x(0, myvar).writeln; //1234 x2.x(0, myvar).writeln; //1234 } ```
Wait, that's not too shabby to use the this pointer for a key to an AA. It isn't really a single static variable however, but rather an AA that contains the static variables.
Jul 20 2021
prev sibling parent cc <cc nevernet.com> writes:
On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:
 Is there a way to make myvar local to each instance of `X` 
 without making it a variable of `X`? Just curious.
Sorry if I missed something obvious but is there a specific reason why it isn't just a class member variable? ```d class X { int myvar = 1234; int x(int param) { if (param == 0) return myvar; else { myvar = param; return myvar; } } } ``` ?? Why would you need a static variable inside a method but also have that static variable unique to each class instance, but not stored inside the class? I could see maybe if the class definition were private and you can't change it, in which case you could extend it: ```d class X { // Someone else's module } class MyX : X { int myvar = 1234; int x(int param) { return param ? myvar = param : myvar; } } void main() { auto x1 = new MyX(); auto x2 = new MyX(); x1.x(0).writeln; x2.x(0).writeln; x1.x(17).writeln; x2.x(0).writeln; } ```
Jul 22 2021