You can use static variables two ways, 1, a proc var that remains between calls of the proc, and 2, a datum var that is the same across all instances of that datum*.
*datum or object means a generic term for datums, atoms, mobs, obj, turfs, images, clients, etc any "thing" that can have new vars attached to it by the programmer, as well as child types
Proc var:
/proc/getid()
var/static/nextid = 1
. = nextid++
(Note: the part after a = only runs on the first call, afterwards nextid will keep it's value between calls, so the next call would return 2, then 3, then 4, and so on.)
Datum var:
/datum/thingy
var/id
var/static/nextid = 1
/datum/thingy/New()
id = nextid++
Merged:
/datum/thingy
var/id
/datum/thingy/New()
id = getid()
/datum/thingy/proc/getid()
var/static/nextid = 1
. = nextid++
(Note:with datum proc static vars, its also shared across all instances of that datum.)
If you are wondering why you've never heard of this var modifier, it's because it's "officially" called global, both global or static can be used interchangeably:
/proc/getid()
var/global/nextid = 1
. = nextid++
However, it is easy to get them confused with proper global vars:
var/nextid = 1
/proc/getid()
. = nextid++
//same thing as above, but should only be used if your proc also has a variable named nextid:
//. = global.nextid
The `global` var modifier and global variables have 0 relation, and this is confusing, luckily the `static` var modifier does the exact same thing, so that is what I'd advise you use.
It's important you learn to properly
Performance wise, static proc and datum vars are as fast as (and in some cases faster then) proc vars, the fastest kind of variable.
Compile wise global variables and defines both slow down compile time, because now at every variable during compile, byond has to search the big list of global variables and current defines to see if the name is in that list, a non-trivially complex operation so if you can shunt it into a var/static or var/static/const in the proc or type, you get speed without slowing down compile time. I should point out that profiling compile slowdowns is finicky at best, so this entire paragraph can be taken with a grain of salt.
And finally, when defining a variable, you should always aim to give it the smallest scope it needs. This allows you to better control the flow of information between parts of your code, and starting out with this mindset allows you to clearly see in your mind what code will access a given variable, avoids name conflicts with other parts of code, and makes debugging issues easier since you reduced the amount of lines that can even access a given variable, so no unexpected changes. Static vars are just another tool that allows you to avoid abusing globals.
Need to have 1 var shared between multiple "objects"? Rather than make it a global (or a define if it's read only), make it a static or static/const variable on the nearest parent type.
Need a proc to store info between calls that only that proc will access? Rather than make it a global var, make it a proc var.
Need to do both at once? Rather than make it a global var, make it a static proc var on a proc on that datum.
I'm sure there are other examples.
One thing I am wondering though in regards to memory handling:
In the case of the above, is it accurate to say that the variable x, once initialized, will always remain in memory?
I suppose this wouldn't be a huge deal if used sparingly, but better these questions be asked than not.