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.


In reply to Prevent Strings From Being Interpreted As A File Handle by amon

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.