#include
int a = 0;
int b = 0;
void update_state() {
a = b + 1;
b = a + 1;
}
int main() {
for (int i = 0; i < 3; i++) {
update_state();
printf("%d %d\n", a, b);
}
return 0;
}
This will print 1 2
3 4
5 6
which shouldn't be too surprising. What it does _not_ print is: 1 1
2 2
3 3
because "b = a + 1" is reading the "new" value of A, not the "old" value as you might expect if you were a new programmer just skimming through the source. If we wanted that behavior we could write void update() {
int a_old = a;
int b_old = b;
a = b_old + 1;
b = a_old + 1;
}
or void update() {
int a_new = b + 1;
int b_new = a + 1;
a = a_new;
b = b_new;
}
but in both cases we have to introduce new temporary variables to hold a copy of either the "old" or "new" state so we don't clobber one of them. If we could annotate our variable names with "oldness" and "newness" we could write something like this: void update() {
a_new = b_old + 1;
b_new = a_old + 1;
}
But that won't work in plain C because "_old" and "_new" aren't meaningful suffixes. More importantly, we can't realistically implement any way of explicitly distinguishing between old and new values in C++ at all - classes and templates don't quite give us enough flexibility to do so.In this trivial example it's easy to see why the different update() methods produce different results, but in large systems it's surprisingly easy to introduce subtle bugs by changing the order of function calls : ClassA expects to read some "new" state from ClassB, code gets refactored, ClassA now inadvertently reads "old" state from ClassB, everything appears to work fine until one day a timing issue causes ClassA and ClassB to get out of sync and everything blows up.
After looking around at existing programming languages (and some CS papers from Google Scholar), it doesn't appear that any major programming languages support this sort of annotation. The closest you can get is the "<=" operator in Verilog, which means something like "assign the RHS to the LHS, but don't do it yet - do it after the current simulation step is done running".
I feel like this is probably a thoroughly covered topic already, but my research skills are failing to turn up anything relevant. Is there some computer sciencey term I'm unaware of to describe languages that allow for these sorts of old/new distinctions?
(a, b) = (b + 1, a + 1)
The two expressions that add 1 are evaluated first, a tuple containing the anonymous results is created, which is unpacked and assigned to the names on the left side. This sidesteps the problem of old/new values.
One way to rewrite your example to do what you want would be with the following changes:
int g_a = 0;
int g_b = 0;
void update_state( int a, int b ) {
g_a = b + 1;
g_b = a + 1;
}Then call update_state like this:
update_state( g_a, g_b );
This works because in C function parameters are passed by value by default.
As for languages that distinguish "old" from "new" values, I don't know of any and I'm not sure there's a well-defined way to do it apart from function calls.