NAME
Perl::Critic::Policy::References::RequireSlices - Use array and hash slices for multiple lookups
DESCRIPTION
Value slices of arrays and hashes, and key-value slices of hashes, permit selecting multiple indexes/keys/values in a single call. This reduces redundancy of code and permits runtime optimization.
$array[1], $array[3] # no
@array[1,3] # yes
$hash{one}, $hash{two} # no
@hash{qw/one two/} # yes
$hash{$one}, $hash{$two} # no
@hash{$one, $two} # yes
$hash{one}, $hash{two}, $hash{three} # no
@hash{qw/one two three/} # yes
$hash{one}{two}, $hash{two}{one} # yes
$hash{one}{one}, $hash{one}{two} # no
@{$hash{one}}{qw/one two/} # yes
CONFIGURATION
By default, two lookups of the same object in a sequence is considered a violation. In living code, it may be easier to manage rewriting to slices when hitting three lookups. This can be controlled with the minimum option:
[ValuesAndExpressions::RequireSlices]
minimum = 3
This setting represents the number of symbol uses and not the number of elements being selected. In particular, there is no detection of the count of keys inside existing slices:
@hash{qw/one two/}, $hash{three} # okay with minimum=3
NOTES
A violation occurs for array subscripts and hash key 'subscripts' at any level. Violations are attached only to the first occurrence in the list. A list may still have multiple violations, however, such as with:
$hash{one}, $hash{two}, 5, $hash{three}, $hash{four} # no
@hash{qw/one two/}, 5, @hash{qw/three four/} # yes
Written code optimization
Slices are useful when more than one subscript is needed, but the actual code savings is dependent on: V the length of the variable name; N the number of keys referenced; K the total length of the N keynames;
If a hash is used in a literal value-slicing situation:
$hash{one}, $hash{two} takes (N+N*V+2(N-1)+2N+K)
@hash{qw/one two/} takes (1+V+2+4+K+(N-1))
The first is (sigils, variable name redundancy, comma-spaces, curlies, keys). The second is (sigil, variable name, curlies, qw, keys, and the spaces between). Totals are K+4N+NV-2 vs K+N+V+6, so the rewrite reduces space when V+8<N(V+4).
Hash used with variable value-slicing:
$hash{$one}, $hash{$two} takes (N+N*V+2(N-1)+2N+K)
@hash{$one,$two} takes (1+V+2+K+2(N-1))
Totals are K+4N+NV-2 vs K+2N+V+1, so the rewrite reduces space when V+3<N(V+3).
Hash used with literals quoted separately:
$hash{one}, $hash{two} takes (N+N*V+2(N-1)+2N+K)
@hash{'one', 'two'} takes (1+V+2+2N+K+2(N-1))
Totals are K+4N+NV-2 vs K+4N+V+1, so the rewrite reduces space when V+3<N(V+1).
Hash reference with literal postfix dereferencing:
$href->{one}, $href->{two} takes (5N+NV+2(N-1)+K)
@$href{qw/one two/} takes (2+V+2+4+K+(N-1))
Rewrite reduces space when V+9<N(V+6)
Hash reference with literal postfix dereferencing, and postfix slicing:
$href->{one}, $href->{two} takes (5N+NV+2(N-1)+K)
$href->@{qw/one two/} takes (4+V+2+4+K+(N-1))
Rewrite reduces space when V+11<N(V+6)
For V>0, the right-hand sides increase with N, and the LHS are fixed. For N>=2, N(V+k)>=2V+2k=V+(2k+V)>=V+(2k+1). All of the above inequalities hold, except the separately-quoted case which may be equal in some cases.
BUGS
Key-value slicing is not currently supported.
Perl version is not considered.
Messaging could be a bit more specific.
SEE ALSO
Perl::Critic::Policy::ValuesAndExpressions::ProhibitSingleArgArraySlice