Thread overview
Can static variables in methods be local for each object?
Jul 20, 2021
Mark Lagodych
Jul 20, 2021
Mark Lagodych
Jul 20, 2021
bauss
Jul 20, 2021
Dukc
Jul 21, 2021
bauss
Jul 23, 2021
cc
July 20, 2021

Let's say I have this code:

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.

July 20, 2021

On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:

>
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
July 20, 2021

On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:

>

Let's say I have this code:

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.

July 20, 2021

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.

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:

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
}
July 21, 2021

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.

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:

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.

July 23, 2021

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?

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:

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;
}