12

I saw this line of code in some sources

( $self->{arg} ) = ( ( delete $self->{arg} ) =~ /(.*)/s ) if ${^TAINT}; 

I understand the untainting. I also known delete

My question is, in what circumstances is it necessary or preferred to use the delete, and isn't it enough to use the simpler

( $self->{arg} ) = ( ( $self->{arg} ) =~ /(.*)/s ) if ${^TAINT};

For example

#!/usr/bin/env perl -T

use 5.014;
use warnings;

package Some {
    use Moose;
    has 'arg' => (is => 'rw', isa => 'Str');
    sub doit {
        my $self = shift;
        #( $self->{arg} ) = ( ( delete $self->{arg} ) =~ /(.*)/s ) if ${^TAINT};
        ( $self->{arg} ) = ( ( $self->{arg} ) =~ /(.*)/s ) if ${^TAINT};
    }
};

my $some = Some->new( arg => 'some text' );
$some->doit();
say $some->arg;
Borodin
  • 123,915
  • 9
  • 66
  • 138
Nemo
  • 3,252
  • 3
  • 17
  • 31
  • 1
    I agree with you. Modifying the hash value in place (or, in this case, leaving it unchanged) seems to be equivalent to deleting it and reinserting. Can you say where you have seen this practice? – Borodin Nov 15 '15 at 10:22
  • @Borodin I saw it https://metacpan.org/source/JSWARTZ/Mason-2.24/lib/Mason/Compilation.pm#L105 – Nemo Nov 15 '15 at 10:27
  • 1
    It can make a difference in case of tie()s, but I see none here. Dunno. I'd never think of doing this. – The Sidhekin Nov 15 '15 at 15:19

1 Answers1

3

With a normal hash deleting the value and reinserting will give the same result as modifying it in place.

The commit does not give any information about why he deletes it just that he copies the functionality from Mason 1. But if you look at the source of HTML::Mason::Lexer, you will find this comment:

We need to untaint the component or else the regexes will fail to a Perl bug. The delete is important because we need to create an entirely new scalar, not just modify the existing one.

($current->{comp_source}) = (delete $current->{comp_source}) =~ /(.*)/s if taint_is_on;

So the reason of doing it this way is to have a new scalar, although he does not do that for the other place where he is untainting: Mason::Interp, so my guess is an earlier Perl bug, when untainting.

So the difference is that with delete will give you a new scalar, although this will seldom have a practical application. (Delete and insert is also a slower operation of course.)

use strict;
my $hash->{test} = 'test';
print \($hash->{test}),"\n";
( $hash->{test} ) = ( ( $hash->{test} ) =~ /(.*)/s );
print \($hash->{test}),"\n";
( $hash->{test} ) = ( ( delete $hash->{test} ) =~ /(.*)/s );
print \($hash->{test}),"\n";

gives

SCALAR(0x7f84d10047e8)
SCALAR(0x7f84d10047e8)
SCALAR(0x7f84d1029230)
HoldOffHunger
  • 10,963
  • 6
  • 53
  • 100
bolav
  • 6,612
  • 2
  • 16
  • 41