named Perl::Critic::Policy::References::ProhibitComplexDoubleSigils. The idea is quite simple and I find myself agreeing with it:
when dereferencing a reference you can omit braces; while this is often not a good habit (because it can become
quite difficult to read a complex reference), it can work out on simpler cases:
#!env perl use v5.20; my %hash = ( key1 => "value1" , key2 => "value2" , key3 => "value3" ); my $hash_ref = \%hash; while ( my ( $k, $v ) = each %$hash_ref ){ say "$k --> $v"; }
In the above code it is quite simple to understand that
@$hash_ref
refers to the whole hash without the need to usethe braces around.
I recognize the advantages of using the braces as:
- a good habit;
- a way to do a good refactoring in the case the reference points to a multidimensional structure.
Anyway simple idioms should stay simple and so should the checkers manage them.
If I run
perlcritic
against the above piece of code, the Perl::Critic::Policy::References::ProhibitDoubleSigilswill report
% perlcritic --single-policy=ProhibitDoubleSigils p.pl Double-sigil dereference at line 12, column 30. See page 228 of PBP. (Severity: 2)
Now, using the above mentioned Perl::Critic::Policy::References::ProhibitComplexDoubleSigils the result becomes:
% perlcritic --single-policy=ProhibitComplexDoubleSigils p.pl p.pl source OK
Ok, let's refactor the program and transform the plain hash in a multidimensional one:
#!env perl use v5.20; my %hash = ( key1 => "value1" , key2 => "value2" , key3 => "value3" ); my %outer_hash = ( config1 => \%hash ); my $hash_ref = \%outer_hash; while ( my ( $k, $v ) = each %{ $hash_ref->{config1} } ){ say "$k --> $v"; }
The above part is the right way of dereferencing the reference to the inner hash, and it does use curly braces
and makes
Perl::Critic
, both policies, not complaining at all.If, instead, we pretend to use double sigils (that is removing the arrow operator) the code becomes:
#!env perl use v5.20; my %hash = ( key1 => "value1" , key2 => "value2" , key3 => "value3" ); my %outer_hash = ( config1 => \%hash ); my $hash_ref = \%outer_hash; while ( my ( $k, $v ) = each %{ $$hash_ref{config1} } ){ say "$k --> $v"; }
and of course both policies complain about:
% perlcritic --single-policy=ProhibitDoubleSigils p.pl Double-sigil dereference at line 13, column 33. See page 228 of PBP. (Severity: 2) % perlcritic --single-policy=ProhibitComplexDoubleSigils p.pl Complex double-sigil dereferences at line 13, column 33. Found complex double-sigil dereference without curly braces. (Severity: 2)
Something similar happens when you try to extract a single scalar value from the nested hash:
... # line 20 my $k1 = $$hash_ref{ config1 }->{ key1 }; say "key1 is $k1"; # line 23 $k1 = $hash_ref->{ config1 }->{ key1 }; say "key1 is $k1";
both the above instructions place the correct value into the
$k1
variable, and the policies both complain about the first line(the one with the
$$
):% perlcritic --single-policy=ProhibitDoubleSigils p.pl Double-sigil dereference at line 20, column 10. See page 228 of PBP. (Severity: 2) % perlcritic --single-policy=ProhibitDoubleComplexSigils p.pl The value for the global "single-policy" option ("ProhibitDoubleComplexSigils") did not match any policies (in combination with other policy restrictions).
Summing up the idea is to allow double sigils only when you are dereferencing a single level, not for complex data structures.
Nessun commento:
Posta un commento