On Tue, 25 Jan 2022 13:20:17 +0000 hv@crypt.org wrote: > Why can't we? I think I might have known the answer once, but if I did > I no longer recall it. > > I think of local() as "temporarily replace the value at this lvalue > with a new value, restore it at the end of the current lexical scope". > This is hugely useful in many situations that would otherwise require > more and slower code with much more opportunity for error. People often think of `local` as being equivalent to saving the old value of a variable, assigning a new value, and arranging to assign the new value back in. Perhaps equivalent to this using our new `defer` blocks: { my $saved_VAR = $VAR; defer { $VAR = $saved_VAR; } $VAR = $new; ... } That's not really how it works at all though - don't forget that `local` is a very old Perl feature that massively predates `my` variables. In fact, `local` isn't about values but about variables. What `local` really does is temporarily moves a *variable* out of the way, assigning a new one into its place, to be restored back again. Variables themselves can only be moved around where they exist by reference - as members of the symbol table (i.e. `our` variables), or elements of aggregate structures (arrays and hashes). Because regular lexical scalars do not have this one-layer-distant referencing effect, they cannot be moved out of the way by `local`. This distinction isn't often visible, but it does come up for example when you consider `tie`, or other magics applied to variables. > Is there a technical reason why it would not be possible to implement? > Or is it that we're worried it would be confusing for users? Or is it > only that way back when (around 5.0, I guess) nobody thought it would > be useful? > > Is it something we would ever consider changing? Yes and no. Since it's detected at compiletime, it would be quite easy for the parser to implement a totally different kind of `local`isation - one that acts on values - when dealing with lexical variables. That may confuse users, because it would act differently for the purposes of tie/magic. My preference would be to add a new keyword (because "local" is a terrible name anyway) to have the effect of temporarily assigning a new *value* to any lvalue expression, and arranging for its old value to be restored again at end of scope. In fact I already wrote a module to provide a `dynamically` keyword doing just that: https://metacpan.org/pod/Syntax::Keyword::Dynamically As compared `local` it has three key differences: 1) Can `dynamically` modify a regular lexical variable 2) Can `dynamically` modify any lvalue-returning function or method. Very handy for accessor-type methods on objects: dynamically $logger->level = LOG_DEBUG; 3) Interacts with the `async/await` syntax provided by Future::AsyncAwait, to properly swap the values around when context switching: async sub f { dynamically $logger->level = LOG_DEBUG; await some_operation(); $logger->print( "Still in debug level here" ); } Bringing this keyword into perl core would be easy enough for the first two points, but the third would be a tough sell because it first depends on having async/await implemented in core. Arguing that into perl core at the moment would be a Fun and Exciting challenge ;) -- Paul "LeoNerd" Evans leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/Thread Previous | Thread Next