On Thu, May 27, 2021 at 07:56:16AM -0000, Shreyan Avigyan wrote:
Lot of programming languages have something known as static variable storage in *functions* not *classes*. Static variable storage means a variable limited to a function yet the data it points to persists until the end of the program.
+1 on this idea. One common use for function defaults is to optimize function lookups to local variables instead of global or builtins: def func(arg, len=len): # now len is a fast local lookup instead of a slow name lookup Benchmarking shows that this actually does make a significant difference to performance, but it's a technique under-used because of the horribleness of a len=len parameter. (Raymond Hettinger is, I think, a proponent of this optimization trick. At least I learned it from his code.) If functions had static storage that didn't need to be declared in the function parameter list, then we could use that for this trick. As you correctly point out:
Well Python also kind of has that functionality. Python's default values provide the same type of functionality
Indeed: def func(static_storage=[0]): static_storage[0] += 1 print(static_storage[0]) But that's kinda yucky for the same reason as above: we have to expose our static storage in the parameter list to the caller, and if the value we care about is immutable, we have to stuff it inside a mutable container.
but it's a *hack*
I disagree that it is a hack. At least, the implementation is not a hack. The fact that the only way we can take advantage of this static storage is to declare a parameter and give it a default value is hacky. So I guess I agree with you :-)
and also *problematic* because only mutable types that are mutated persists. Static should behave much like Python's for loop variables.
I have no idea what that comment about loop variables means.
This idea proposes to add a keyword (static, maybe?) that can create static variables that can persist throughout the program yet only accessible through the function they are declared and initialized in.
Here is a sketch of how this could work, given a function like this: def func(arg): static spam, eggs static cheese = expression ... At function declaration time, the two static statements tell the compiler to: * treat spam, eggs and cheese as local variables (use LOAD_FAST instead of LOAD_GLOBAL for lookups); * allocate static storage for them using the same (or similar) mechanism used for function default values; * spam and eggs get initialised as None; * cheese gets initialised to the value of `expression`, evaluated at function declaration time just as default arguments are. When the function is called: * the interpreter automatically initialises the static variables with the stored values; * when the function exits (whether by return or by raising an exception) the static storage will be updated with the current values of the variables. As a sketch of one possible implementation, the body of the function represented by ellipsis `...` might be transformed to this: # initialise statics spam = LOAD_STATIC(0) eggs = LOAD_STATIC(1) cheese = LOAD_STATIC(2) try: # body of the function ... finally: STORE_STATIC(spam, 0) STORE_STATIC(eggs, 1) STORE_STATIC(cheese, 2) One subtlety: what if the body of the function executes `del spam`? No problem: the spam variable will become undefined on the next function call, which means that subsequent attempts to get its value will raise UnboundLocalError: try: x = spam + 1 except UnboundLocalError: spam = 0 x = 1 I would use this static feature if it existed. +1 -- Steve