The indirect object call syntax is a grammatical mechanism used by Perl to parse method calls. It is commonly used to emulate other language syntax. For instance, if a class Class has a constructor named new, then both of these statements invoke this constructor:

my $obj1 = Class->new; # 'object-oriented' syntax
my $obj = new Class; # 'indirect object' syntax

The perlobj manpage [Wall 2011] states the following:

The -> notation suffers from neither of these disturbing ambiguities, so we recommend you use it exclusively. However, you may still end up having to read code using the indirect object notation, so it's important to be familiar with it.

Consequently, indirect object syntax shall not be used.

Noncompliant Code Example

This noncompliant code example demonstrates some of the hazards of using indirect call syntax.

{
  package Class;
  sub new {
    my $class = shift;
    my $arg = shift;
    my $self = bless( {Arg=>$arg}, $class);
    print "Class::new called with $arg\n";
    return $self;
  }
}

sub new {
  my $arg = shift;
  print "::new called with $arg\n";
}


my $class_to_use = Class;

my $b1 = new Something;       # Invokes global new
my $b2 = new Class Something; # Invokes Class::new
my $b3 = new $class_to_use;   # Surprise! invokes global new! 

In this code, the last three statements use indirect object syntax to invoke a new subroutine. However, the Perl interpreter can easily misinterpret which subroutine is actually meant to be invoked. This behavior can be especially dangerous if the methods to be invoked live in different packages.

Compliant Solution

In this compliant solution, the final three statements all use direct object syntax, explicitly making their intent clear to both the developer and the Perl interpreter.

# ...

my $class_to_use = Class;
my $b1 = new( Something);                # Invokes global new
my $b2 = Class->new( Something);         # Invokes Class::new
my $b3 = $class_to_use->new( Something); # Invokes Class::new

Risk Assessment

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

OOP32-PL

Low

Probable

Medium

P4

L3

Automated Detection

Tool

Diagnostic

Perl::Critic

Objects::ProhibitIndirectSyntax

Bibliography


1 Comment

  1. Anonymous

    This ignores the problem with 'direct' object call syntax:

    use JSON;

    sub JSON {

      return BadJSON::->new;

    }

     

    my $j = JSON->new;

     

    the last line is actually interpreted as JSON()->new so you get a BadJSON object instead of a JSON object.  The way to avoid this is make the fact that JSON is a package explicit (JSON:: instead of JSON), but this also defuses some of the 'problems' with indirect object syntax: my $j = new JSON::;

    As to the non-compliant code (which seems to avoid strict and warnings just to make its point), indirect object syntax shouldn't be expected to work on string scalars ('Class' in this case), only on literal package names (with or without final :: ) or blessed objects.