The title pretty much sums it up, but here's the long version anyway.
After posting a small snippet of perl code, I was told to avoid indirect object notation, "as it has several side effects". The comment referenced this particular line:
my $some_object = new Some::Module(FIELD => 'value');
As this is how I've always done it, in an effort to get with the times I therefore ask:
- What's so bad about it? (specifically)
- What are the potential (presumably negative) side effects?
- How should that line be rewritten?
I was about to ask the commenter, but to me this is worthy of its own post.
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:
In that code,
new SubWidget
is expected to meanInstead, it actually means
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: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
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,
On the plus side, using
no indirect;
helps the first problem.The correct way to write the method call is the following:
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:The main problem is that it's ambiguous. Does
mean to call the
new
method in theSome::Module
package, or does it mean to call thenew
function in the current package with the result of calling theModule
function in theSome
package with the given parameters?i.e, it could be parsed as:
The alternative is to use the explicit method call notation
Some::Module->new(...)
.Normally, the parser guesses correctly, but the best practice is to avoid the ambiguity.
The commenter just wanted to see
Some::Module->new(FIELD => 'value');
as the constructor.Perl can use indirect object syntax for other bare words that look like they might be methods, but nowadays the
perlobj
documentation suggests not to use it.The general problem with it is that code written this way is ambiguous and exercises Perl's parser to test the namespace to e.g. check when you write
method Namespace
whether Namespace::method exists.As to how to avoid it: There's a CPAN module that forbids the notation, acting like a pragma module:
http://metacpan.org/pod/indirect