Upstream-Dependent Value Assignment
Concept
What would it feel like to use a high-level programming language where the common imperative syntax of assigning values to variables also setup a dependency tree on upstream values?1
a = 5
b = a + 2 // because a is in this expression, b is marked as dependent on a
print(a) // prints 5
print(b) // prints 7
a = 8 // because b is dependent on the value of a, it also gets updated
print(a) // prints 8
print(b) // prints 10
Or how it might be implemented: the simple-looking variable assignment is actually a function definition; and the simple-looking variable reference is actually a function invocation! (To represent this in JavaScript, I'll need to use a global object to hold the functions so I can reference them by name only.)
G = {} // "G" for "globals"
G["a"] = () => { return 5 }
G["b"] = () => { return G["a"]() + 2 }
console.log(G["a"]())
console.log(G["b"]())
G["a"] = () => { return 8 }
console.log(G["a"]())
console.log(G["b"]())
One implication I can imagine is that within a body of code, relationships between variables can be setup in any order as long as the resulting values occur after all relations are setup.
name = first_name + " " + last_name
greet = () => { print(name) } // let's borrow from JS's anonymous function syntax
first_name = "ada"
last_name = "lovelace"
greet()
// There's no issue as long as this is called after greet's dependency tree:
// greet
// └── name
// ├── first_name
// └── last_name
Extending the Idea
Of course, in programming we often want to reference an old value rather than always using the latest. In most languages, we accomplish this by simply not re-assigning the old variable.
a_1 = 5
a_2 = 8
console.log(a_1) // because we want to see the original value of a
We'll want some language-level way to indicate a pinned variable. This could be a keyword or an operator. Below there's two new syntactic solutions: the @ operator and the keyword now.
a = 5
original_a = a@now
b = a + 2
print(a)
print(b)
a = 8
print(a) // 8
print(b) // 10
print(original_a) // 8
This syntactic affordance could easily be used in languages that don't have this post's proposed upstream dependent value assignment feature. I'm proposing here that the @ operator indicate "the value of the left operand at the time of the right operand"; and the now keyword would mean ... "the state of the code at this line or time".
Times could be marked with other names than "now":
a = 5
mark setup
b = a + 2
mark change
print(a)
print(b)
a = 8
print(a) // 8
print(b) // 10
print(a@setup) // 8
This feels like line-oriented programming languages (think "LABEL" and "GOTO"), but the key difference being: we're only looking at past values of a variable (like a transaction log) not spaghetti'ing our way through the past to emulate modern control flow patterns.
Checking the value of a variable at a particular time could even include relations defined after that time! Notice below how the @setup takes us back to when a = 5 (long before b was defined), but we're still able to see what value b would have had!
a = 5
mark setup
a = 8
a = 10
a = 15
b = a + 2
print(b) // 17
print(b@setup) 7
Conclusion
All in all, this kind of language feature seems at least neat and potentially useful in isolation. I'm not proposing this as a feature that every language should implement. Instead I hope this provides language creators some inspiration for what could be included in their languages!
I'm always looking for better names, so if you have one for "dependency tree on upstream values", let me know!↩