http://qs321.pair.com?node_id=1083985

amon has asked for the wisdom of the Perl Monks concerning the following question:

Perl has the feature that strings named like a file handle are taken to be a file handle, which for example means that “open DUP, '>&STDOUT'”, but also “'STDOUT'->say("hello")” works.

This leads to conflicts if we have a class and a bareword file handle of the same name:

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.

I am aware that this can be avoided with lexical filehandles, and that adhering to proper naming conventions makes this collision less likely. For example, the above code does not fail if the script is in “package Foo” and the eval'd code in “package main”, but the problem occurs again when we do “'main::Input'->awesome” which should in theory be absolutely equivalent to “'Input'->awesome”.

However, my question is: How can I disambiguate a method call on a string so that it is always resolved as a class method call, and not as a call on an IO instance?

I assume one would have to write a pragma to hook into method resolution, e.g. by replacing the pp_method_named opcode, but I'd much rather hear the wisdom of more experienced monks on this.

Context: I'm hacking on the utility module Util::Underscore that misguidedly stuffs various utils into the “_” namespace so that they can be used comfortably without having to import them. As I want to prevent the “_” package from being used directly, I boobie-trapped the “_::import” method to blow with a helpful error message whenever touched. My tests started failing when another module contained file tests on the magic “_” file handle, like “-d $file && -w _”.

This question has previously been asked on Stack Overflow, but so far without the answer I'm seeking.