|
It's a stack-local global variable. Here's one case where I wished I had it. I was writing a tool (in Python) for some scientific task. Parse a file, do some calculations, call out to some library to do more calculations. The whole thing was pretty complex, but cleanly architectured. But then the requirements changed. I had to do something different in the innermost function, depending on the configuration. This was probably 6 layers of functions deep. Now I had two options: add another parameter to every function to carry my configuration variable, or put everything in a class and use a member field. I couldn't use global variables, since I was doing many of these calculations concurrently. And I didn't want to add new parameters, since it clutters the code, and it mixes different levels of abstraction. Most of the intermediate functions don't care about what's going on at the lowest level. Yes it changes their output, so from strictly "functional" best practices I should string along a parameter. But it felt wrong anyway. So what I did was cram everything in a class and call it a day. With dynamic scoping, I could have put the configuration in a dynamically scoped variable. Ideally, there would be a way to specify that a function takes dynamic scope. Then tooling would understand that all the intermediate functions have a controlled amount of impurity. In pseudocode: MyResult myCalculation(float mass, float energy) (dynamic string extratext) {
// do the calculation and add extra text to the result
}
// way up the call stack:
using dynamic extratext = "Preliminary, do not publish" {
calculateAllTheThings();
}
I know this goes against the current trends (make functions pure if possible, avoid mutable state, think a certain way about data flow...). But in practice, those trends sometimes work fine, and sometimes produce convoluted code. In some cases, I find it easier to produce code that looks clean and functional from a domain logic POV, and add stuff that is orthogonal to it (logging, presentation, ...) via a different mechanism. |