I was playing around with the idea of having global variables.. With nested scopes.. In a threaded environment. Yes, I’m aware that a global variable with scope isn’t a global variable – but.. it works.. though doesn’t really make sense. Actually, it does make sense, but the terminology is off. Basically, its a global variable whose value depends on the scope in which its used. Quick code example?
ScopedGlobal<int> global = 5; // Global scoped global.
void foo () {
ScopedGlobal<int> global = 4; // Local scoped global.
output("Value in foo: ", global); // Print 4
}
void bar () {
output("Value in bar: ", global); // Print 5
}
Ok, that code clearly won’t compile in C++, but its just an example. Also, it proves nothing – the local variant simply aliases the global. What I had in mind is a little more complex than this – what if the local version can be passed to a different scope and still be valid? Perhaps to another thread? Like how a closure captures its enclosing environment – a local variable could capture its environment and carry it along with it, to another scope or another thread. Capturing the entire environment could be a bit of effort, but a simple variable doesn’t need to – its not a function which references its environment, its just a value which needs to retain its state in various scopes. This can actually be implemented in C++ with a little effort and even made thread safe so it can be passed between threads. You can take a look at my test code here. Of course, my little test only allows the creation of one of these, since the global access is handled through static variables – but you could keep a table that can be accessed to store a number of variables, so it can actually be implemented in plain C++.
But, thats besides the point of this article. It is, however, the background information for my newest and craziest language concept. I’m unsure if I should add an “esoteric language” tag to this post or not
What if scopes were elastic? They could change and move around, altering the state of your variables and program transparently to its execution. Perhaps elastic scopes could even be seen as a computation paradigm? Then again, I’m not going to go to the effort of figuring out how to turn elastic scopes into a turing complete execution model – but I am going to theorize how they could be used as part of an execution environment in a highly parallel system.
Instead of functions, I am going to use named scopes, which can be called asynchronously and whose environments can be read from or sent to by other scopes. Heres some possible sample code:
scope1 = {
var val = "in scope1"
print "scope1 " val
async {
scope2 = {
val = "in scope2"
print "scope2 " val
sleep 500
print "scope2 " val
}
scope3 = {
print "scope3 " val
sleep 100
print "scope3 " val
val = "in scope3"
print "scope3 " val
send scope3 to scope2
}
}
print "scope1 " val
}
And the output would be something like the following:
scope1 in scope1 scope3 in scope1 scope2 in scope2 scope3 in scope1 scope3 in scope3 scope2 in scope3 scope1 in scope1
Spaghetti code, of course, but overall, simple enough so far.
So far, its nothing too special, besides perhaps sending the value of val from scope3 to scope2. But imagine, for a moment, what would happen if the value was passed, as an argument, to a function which is executed in its own thread. What if it was passed in such a way that its scope was retained? Lets see an example:
function f1 (var v) {
print v
sleep 500
print v
}
scope1 = {
var val = 5
threat t = f1
f1.start(val)
sleep 100
}
What does the second print output? In a normal language, it would be 5, but if val retains its scope – scope1 – then it will have went out of scope before reacng this print. Imagine that.. scopes changing in other threads could affect your variables! Of course, I’m assuming that accessing a variable is always atomic. This would be extremely important in such a language.
Am I going to design a lnaguage around this idea? No, of course not and I shudder to think of all the changing state! Shared state is evil and makes concurrency hard. Yet here I take shared state and make it even more unpredictable than before. But, the idea is still interesting. Could it be used to do wonderful things? Can it be used with immutable data structures? What is an immutable data structure in a mutable, elastic scope? Is it, essentially, mutable? Can this be used as part of a dataflow language to do weird and wonderful things? Or was this a pointless exercise? These are all open questions and I invite people to play with them and see what happens. I will ammend this post after toying with the concept some more.