NAME

Perl::Critic::Policy::Misc::ProhibitMethodsInStringConcat - Prohibit method calls in string concatenation

VERSION

version 0.02

DESCRIPTION

This policy flags method calls used as operands to the . (string concatenation) operator.

Why?

When Perl concatenates strings and an operand is undef, it emits a warning. The quality of that warning depends on the operand's form:

my $result = "Name: " . $obj->name() . " Age: " . $obj->age();

produces:

Use of uninitialized value in concatenation (.) or string at ... line N

No indication of which method returned undef. On a long concatenation line the developer must manually bisect to find the offending call.

By contrast, assigning the result to a variable first:

my $name = $obj->name();   # warns: Use of uninitialized value $name ...
my $age  = $obj->age();
my $result = "Name: " . $name . " Age: " . $age;

Perl names the variable:

Use of uninitialized value $name in concatenation (.) or string at ... line N

The variable name pinpoints the source of undef immediately.

This difference matters because method calls are opaque - the call expression has no name that Perl can surface in the diagnostic. A scalar variable, on the other hand, carries its identifier through to the warning.

Note that method calls passed as arguments to printf / sprintf suffer from the same problem - Perl's warning will not name which argument returned undef. Assigning to a variable first is the only way to get a named warning.

Remediation

# Instead of - method call hidden inside concat:
my $result = "Name: " . $obj->name() . " Age: " . $obj->age();

# Unload to a variable first (fixes the warning):
my $name = $obj->name();
my $age  = $obj->age();
my $result = "Name: " . $name . " Age: " . $age;

EXAMPLES

my $x = "Hello " . $obj->name();      # not ok

my $x = $obj->name() . "Hello";       # not ok

my $x = 'hello' . ( $foo->bar / 2 ) . 'there';  # not ok (method in parens)

my $name = $obj->name();              # ok - unload to variable first
my $x    = "Hello " . $name;

The policy traverses into parentheses, so method calls nested inside parenthesized sub-expressions within a concatenation are also flagged.

.= (concat-assign)

The .= operator is not flagged when used with a single method call:

$x .= $obj->method();   # ok - single method, clear intent

However, when the right side of .= itself contains . concatenation with method calls, those inner . operators are flagged:

$x .= $obj->method() . $obj->other();   # not ok (inner .)
$x .= "Name: " . $obj->method();        # not ok (inner .)

CONFIGURATION

This policy does not accept any configuration parameters.

RELATED POLICIES

Perl::Critic::Policy::ControlStructures::ProhibitMultipleSubscripts follows the same principle of extracting intermediate results into named variables rather than inlining complex expressions in a loop. Just as this policy flags method calls inside string concatenation (assign to a variable first for better diagnostics), ProhibitMultipleSubscripts flags repeated subscript lookups in a loop (assign to a variable first for efficiency and clarity).

SEE ALSO

Perl::Critic, "Use of uninitialized value %s" in perldiag

AUTHOR

Dean Hamstead <dean@fragfest.com.au>

COPYRIGHT AND LICENSE

This software is Copyright (c) 2026 by Dean Hamstead.

This is free software, licensed under:

The MIT (X11) License