Perl has the feature that strings named like a file handle are taken to be a filehandle:
# let this be some nice class I wrote
package Input {
sub awesome { ... }
}
So when we do Input->awesome
or extra-careful: 'Input'->awesome
, the method will get called. Unless:
# now somewhere far, far away, in package main, somebody does this:
open Input, "<&", \*STDIN or die $!; # normally we'd open to a file
This code doesn't even have to be executed, but only be seen by the parser in order to have Perl interpret the string 'Input'
as a file handle from now on. Therefore, a method call 'Input'->awesome
will die because the object representing the file handle doesn't have awesome methods.
As I am only in control of my class but not of other code, I can't simply decide to only use lexical filehandles everywhere.
Is there any way I can force Input->awesome
to always be a method call on the Input
package, but never a file handle (at least in scopes controlled by me)? I'd think there shouldn't be any name clash because the Input
package is actually the %Input::
stash.
Full code to reproduce the problem (see also this ideone):
use strict;
use warnings;
use feature 'say';
say "This is perl $^V";
package Input {
sub awesome {
say "yay, this works";
}
}
# this works
'Input'->awesome;
# the "open" is parsed, but not actually executed
eval <<'END';
sub red_herring {
open Input, "<&", \*STDIN or die $!;
}
END
say "eval failed: $@" if $@;
# this will die
eval {
'Input'->awesome;
};
say "Caught: $@" if $@;
Example output:
This is perl v5.16.2
yay, this works
Caught: Can't locate object method "awesome" via package "IO::File" at prog.pl line 27.
Using the bareword
Input
as a filehandle is a breach of the naming convention to have only uppercase barewords forFILEHANDLE
s and Capitalized/CamelCased barewords forClass
es andPackage
s.Furthermore lexcial
$filehandles
have been introduced and encouraged already a very long time ago.So the programmer using your class is clearly misbehaving, and since namespaces are per definition global this can hardly be addressed by Perl (supporting chorobas statement about begging for problems).
Some naming conventions are crucial for all (dynamic) languages.
Thanks for the interesting question though, the first time I see a Perl question in SO I would preferred to see on perlmonks! :)
UPDATE: The discussion has has been deepened here: http://www.perlmonks.org/?node_id=1083985
Using the same identifier for two different things (a used class and filehandle) begs for problems. If your class is used from a different class that's used in the code that uses the filehandle, the error does not appear:
My1.pm
My2.pm
script.pl