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

I have a question concerning FileHandle.

my $fh = FileHandle->new(">./test"); print $fh "Hello\n";

works just fine, however

$hashref->{"fh"} = FileHandle->new(">./test"); print $hashref->{"fh"} "Hello\n";

does not compile: "String found where operator expected"
Why?

$hashref->{"fh"}->print()

works though.

Replies are listed 'Best First'.
Re: FileHandle in a Hashref
by toolic (Bishop) on Feb 25, 2011 at 14:36 UTC
    From print:
    Note that if you're storing FILEHANDLEs in an array, or if you're using any other expression more complex than a scalar variable to retrieve it, you will have to use a block returning the filehandle value instead:
    use warnings; use strict; use FileHandle; my $hashref; $hashref->{"fh"} = FileHandle->new(">./test"); print { $hashref->{"fh"} } "Hello\n";
Re: FileHandle in a Hashref
by moritz (Cardinal) on Feb 25, 2011 at 15:45 UTC
    Why?

    In print $handle @args the $handle is syntactically distinct from an ordinary argument in there is no space between it and the following arguments.

    This is forbidden in "normal" perl code, we call it "two terms in a row" (short TTIAR)

    So if Perl allowed arbitrary expressions as file handles, it wouldn't catch TTIAR errors later, leading to extremely weird behavior. Consider

    print $some + $var * 5 3; # ^ # forgot an operator

    In this example, everything up to (and including) the 5 would be parsed as a file handle if Perl allowed arbitrarily complex expressions as file handles. No syntax error would be emitted.

    So, there needs to be a complexity limit as to what is allowed as a file handle. The choice is "a single variable, bareword or { ... } block".

Re: FileHandle in a Hashref
by Marshall (Canon) on Feb 25, 2011 at 14:38 UTC
    I added an extra set of curly braces and that works. Evidently with this syntax, you have to "help" things out a little bit to get the value of "fh" otherwise it doesn't parse right. So this is how to make it work. Exactly why this is necessary is a syntax issue that I don't know the answer to.
    #!/usr/bin/perl -w use strict; use FileHandle; my $hashref->{"fh"} = FileHandle->new(">test"); print {$hashref->{"fh"}} "Hello\n";