What's so bad about it?
The problems with Indirect Method Notation are avoidable, but it's far easier to tell people to avoid Indirect Method Notation.
The main problem it's very easy to call the wrong function by accident. Take the following code, for example:
package Widget;
sub new { ... }
sub foo { ... }
sub bar { ... }
sub method {
...;
my $o = new SubWidget;
...;
}
1;
In that code, new SubWidget
is expected to mean
SubWidget->new()
Instead, it actually means
new("SubWidget")
That said, using strict will catch most of these instances of this error. Were use strict;
to be added to the above snippet, the following error would be produced:
Bareword "SubWidget" not allowed while "strict subs" in use at Widget.pm line 11.
That said, there are cases where using strict would not catch the error. They primarily involve the use of parens around the arguments of the method call (e.g. new SubWidget($x)
).
So that means
- Using Indirect Object Notation without parens can result in odd error messages.
- Using Indirect Object Notation with parens can result in the wrong code being called.
The former is bearable, and the latter is avoidable. But rather than telling people "avoid using parens around the arguments of method calls using Indirect Method Notation", we simply tell people "avoid using Indirect Method Notation". It's just too fragile.
There's another issue. It's not just using Indirect Object Notation that's a problem, it's supporting it in Perl. The existence of the feature causes multiple problems. Primarily,
- It causes some syntax errors to result in very odd/misleading error messages because the code appeared to be using ION when it wasn't.
- It prevents useful features from being implemented since they clash with valid ION syntax.
On the plus side, using no indirect;
helps the first problem.
How should that line be rewritten?
The correct way to write the method call is the following:
my $some_object = Some::Module->new(FIELD => 'value');
That said, even this syntax is ambiguous. It will first check if a function named Some::Module
exists. But that's so very unlikely that very few people protect themselves from such problems. If you wanted to protect yourself, you could use the following:
my $some_object = Some::Module::->new(FIELD => 'value');