kennethk has asked for the wisdom of the Perl Monks concerning the following question:
This seems like it should be possible, but I can't seem to wrap my head around how to get the scope right. I have a complex data structure where I need to temporarily modify some key-values - by doing this I get to reuse some rather complex parsing logic. As code is worth 1000 words, I mean something like:
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @data = ( {unit => 'S', value => 50, }, {unit => 'T', value => 60, }, {unit => 'Q', value => 70, }, ); # Works LOCAL_BLOCK_1: { local $data[0]{unit} = 'S'; local $data[1]{unit} = 'S'; local $data[2]{unit} = 'S'; print Dumper \@data; } print Dumper \@data;
This works well if you know your array length; however I can't figure out how to make this work for an arbitrary-length array. I've tried the following variants:
I understand why none of these work; but it seems like what I want to do should be possible. Right now the actual code looks something like:# Doesn't work LOCAL_BLOCK_2: { local $data[$_]{unit} = 'S' for 0 .. $#data; print Dumper \@data; } # Doesn't work LOCAL_BLOCK_3: { local $_->{unit} = 'S' for @data; print Dumper \@data; } ## Doesn't work, fatal #LOCAL_BLOCK_4: { # local map {$_->{unit}} @data; # $_->{unit} = 'S' for @data; # # print Dumper \@data; #}
The parser can die, which results in some misdirection with error messages and potentially corrupt records. Local is so much cleaner here, if only it worked. What am I missing? Is my explicit cache and restore the only solution, with the addition of an catch-and-throw around the value restore?LOCAL_BLOCK: { my @units = map $_->{unit}, @data; $_->{unit} = 'S' for @data; parser(@data); $data[$_]{unit} = $units[$_] for 0 .. $#data; }
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
|
|---|