[Melbourne-pm] When is an lvalue an lvalue?
Jacinta Richardson
jarich at perltraining.com.au
Mon Feb 20 18:17:23 PST 2012
On 20/02/12 18:24, Tim Connors wrote:
> And yet the following exits:
>
> $md5->add(substr($$dataRef, $seekPosn, 131072));
>
> (part of lib/BackupPC/Lib.pm in backuppc, triggered by BackupPC_tarPCCopy
> - I'm pretty sure it's raising an exception, but the path is tortuous,
> not least because I wasn't quite sure why the exit code was 0, but then I
> just realised I was then piping the output to tar on another machine.
> duh)
>
> My workaround stops the premature bailing out:
> my $tmp_str = substr($$dataRef, $seekPosn, 131072);
> #print STDERR "gothere3\n";
> $md5->add($tmp_str);
Ooo, that's really interesting.
I originally thought the issue was that you were passing in a literal (the
return value of substr) and then attempting to change it, despite your
conviction that it isn't being changed. But it looks likes the return value of
substr *isn't* a literal, it's a magical anchor (which makes sense given the
lvalue stuff). This means it's not a copy of your data, it *is* your data.
That's fascinating.
And awesome. I've always thought you had to do the lvalue stuff like this:
substr($string, $offset, $length) = $replacement;
But instead, if it's an anchor, then it means you can do this:
use v5.10.0;
my $string = "The quick brown fox jumps over the lazy dog";
my $offset = 16;
my $length = 3;
my $replacement = "kitten";
say $string;
naughty( substr($string, $offset, $length) );
say $string;
sub naughty {
$_[0] = $replacement;
}
__END__
The quick brown fox jumps over the lazy dog
The quick brown kitten jumps over the lazy dog
But of course if you instead call:
naughty( substr($string, 100, 1) );
then you get:
substr outside of string at substr.pl line ...
But if you can capture those anchors... that's awesome. So then you can do
stuff like this:
naughty2( $string, substr($string, 16, 3), substr($string, 40, 3));
say $string;
sub naughty2 {
# mess with $string if you want...
substr($_[0], 3, 16, "elephant");
# mess with the anchors
$_[1] = "eel";
$_[2] = "running horse";
}
__END__
# and then wonder what comes out
The quick brown eelphant jumps over the running horsey dog
> Not really an lvalue, is it? I can sort of see why it does that - it
> doesn't know that the value is being passed to a function that isn't then
> going to modify its arguments, but ... counterintuitive. I wonder if
> there's another way substr could have handled the returning of null data
> that pleases legacy programs that don't follow perl best practices.
So, while I can't actually answer your question, I can agree entirely that
you're dealing with lvalue magic. :)
This is indeed an issue only with 3 argument substr. Although, interestingly,
it seems that the 4 argument substr still returns an anchor into the string,
just not a magical string changing one. Otherwise:
naughty2( $string, substr($string, 16, 3, "hippopotamus"), substr($string,
40, 3));
would throw an error (about modifying a literal), and it doesn't.
J
More information about the Melbourne-pm
mailing list