John M. Dlugosz has asked for the wisdom of the Perl Monks concerning the following question:

Puzzle me this:

Given that

my $m=preprocess::scanfile ($ARGV[0]); print $m;
works just fine, why does
print (preprocess::scanfile ($ARGV[0]));
not work?

It produces a error "print() on unopened filehandle preprocess::scanfile"

Without the outer parens, I can understand that it looks like an indirect object, and other posts here have pointed out that this takes precedence. But with the parens, it looks like a function, so "it is a function", right?! Why does it still think it's an indirect object?

—John

Replies are listed 'Best First'.
Re: 'print' puzzle
by chipmunk (Parson) on Nov 12, 2001 at 09:39 UTC
    Try either of these:
    print +(preprocess::scanfile ($ARGV[0])); print (preprocess::scanfile($ARGV[0]));
    (Sometimes whitespace does matter! :)
(jeffa) Re: 'print' puzzle
by jeffa (Bishop) on Nov 12, 2001 at 09:53 UTC
    chipmunk and blakem are both correct - & also works here as well:
    print &preprocess::scanfile ($ARGV[0]);

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    F--F--F--F--F--F--F--F--
    (the triplet paradiddle)
    
      OK, so if it's a context problem, I can see that scanfile will see that it was called with "wantarray". But why does print think that's an indirect object, even with parens around it?

      —John

        Make sure that when you say "context", you're not thinking "scalar" and "list" context. Those don't apply here. Read on...
        print FOO $bar;
        Puts the contents of $bar on the filehandle FOO. We're all clear on that.
        print(FOO $bar);
        Does exactly the same thing in a nicely Perl 4-ish way. Perl's parser knows that the first argument to print (regardless of the parens) might be a filehandle which won't be comma-separated from the first thing to be printed. Now:
        print(Package::FOO $bar);
        Falls into the same trap. You're just specifying the package that the filehandle is in. The solutions:
        print +(Package::FOO $bar);
        The + tells the parser that the parens don't go with the print (and therefore the Package::FOO) and they're just grouping. So the parser isn't looking for a filehandle anymore. The Package::FOO gets used with indirect object syntax.
        print(Package::FOO($bar));
        The parser doesn't see a first-argument space-separated from the things to be printed and knows that Package::Foo is Something Else. (Later it'll know it's a function call.)
        print(&Package::FOO $bar);
        Same goes here, the parser doesn't see a filehandle here and knows that it shouldn't go looking here for one.

        I hope that helps. More importantly I hope my lack-of-sleep answer didn't cause more questions than answered...

        I don't think perl is parsing that as an indirect object... it looks like perl interprets your print call as the two argument form: print FILEHANDLE LIST. I can emulate this with the following code:
        #!/usr/bin/perl -wT use strict; package main; print Mymod::mysub (); package Mymod; sub mysub { '123' }
        Which errors out with:
        print() on unopened filehandle Mymod::mysub at ./parensubtest.pl line 5.

        Interestingly enough, if you swap the two stanzas (move lines 7,8 above 4,5) the error disappears.

        A similiar (but not identical) issue was discussed at Filehandles vs. Packages: And the winner is...

        -Blake

Re: 'print' puzzle
by blakem (Monsignor) on Nov 12, 2001 at 09:25 UTC
    just a guess....

    Do either of these work?

    print scalar preprocess::scanfile ($ARGV[0]); print (scalar preprocess::scanfile ($ARGV[0]));
    <P -Blake
(tye)Re: 'print' puzzle
by tye (Sage) on Nov 12, 2001 at 22:27 UTC

    ...or you could just stop putting spaces between your subroutine name and the open paren. This is suggested by "perldoc perlstyle" and will also, as you've found, make you code less likely to be parsed in a way other than you wanted.

            - tye (but my friends call me "Tye")
      Care to elaborate on that?

        #!/usr/bin/perl -w print bareword ("parens"); print bareword( "parens" ); __END__ Unquoted string "bareword" may clash with future reserved word at line 3. Filehandle main::bareword never opened at line 3. Undefined subroutine &main::bareword called at line 4.
        Your style choice causes the line to be parsed differently. That style choice used to break even more things but it was determined that "we" should try to support it even though it is generally not liked for use with Perl. Unless you really enjoy finding bugs and quirks in the Perl parser, you should probably just avoid using that particular style.

                - tye (but my friends call me "Tye")