Le Ven 27 Jan 2012 12:25:09, pshangov a écrit :
Show quoted text> When trying to implement a read-only hash with Variable::Magic, I have
> noticed that the 'store' callback gets invoked when using an array slice
> of the hash, or when iterating over an array reference contained within
> the hash (see the attached test.pl). I presume this is due to some
> internal state of the variable changing, but it is possible to
distinguish
Show quoted text> between such changes and actual attempts to change the value of a hash
> key?
The hash slice is causing a 'store' magic call because "for" aliases $_
to the elements of the list, and $_ can possibly be assigned to in the
body of the loop. This is the same mechanism that causes "1 for
$hash{nonexistent_key}" to vivify : perl cannot know at compile time
whether the hash slot will actually be need, so in doubt it creates the
entry at the beginning of the loop. In that regard, it is "correct" for
Variable::Magic to call the magic callback for this construct (in that
it is as correct as perl itself).
If you want to recognize those constructs, you can use the 'op_info'
feature :
use 5.010;
use strict;
use warnings;
use Variable::Magic qw<wizard cast VMG_OP_INFO_OBJECT>;
use Carp 'carp';
my $wizard = wizard(
store => sub {
my $op = $_[-1];
my $name = $op->name;
my $flags = $op->flags;
my $priv = $op->private;
if ($name eq 'hslice' and $flags & 16 and $flags & 128 and not
$priv) {
carp("store '$_[2]'");
}
},
op_info => VMG_OP_INFO_OBJECT,
);
my %hash = (baz => [ qw<qux quux> ]);
cast %hash, $wizard;
@hash{qw<foo>} = 'bar'; # store
{
my @wut = local @hash{qw<foo bar>}; # nothing
}
say for @hash{qw<foo baz>}; # nothing
say for @{$hash{baz}}; # nothing
Vincent.