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

Does anyone know how to fool perl parser to print to a filehandle that is stored in an array or a hash? For example, this works as expected,
$_ = \*STDOUT; print $_ "moo\n";
but this does not even compile:
$_->[0] = \*STDOUT; print $_->[0] "moo\n"; String found where operator expected at a.pl line 2, near "] "moo\n"" (Missing operator before "moo\n"?) syntax error at a.pl line 2, near "] "moo\n"" Execution of a.pl aborted due to compilation errors.
ideas? ( and no, please don't suggest $_=$_->[0], it's no fun)

Replies are listed 'Best First'.
Re: print to a filehandle
by imp (Priest) on Dec 21, 2006 at 13:25 UTC
    $_->[0] = \*STDOUT; print { $_->[0] } "moo\n";

      That syntax never made sense to me. It's correct, but it doesn't feel right. If it's %h = %{ $h }; and @a = @{ $a }, then why isn't it print *{ $_->[0] } "moo\n"? am I going it alone on that? Perhaps I simply dont' understand the context of the filehandle in a print statement.

      Hrm, perldsc leads me to believe it's just another code block (rather than a deref) so the parser can figure out it's a file handle argument ... maybe?

      -Paul

        AFAIK, it's a parser issue (hence the syntax error) caused by the fact that Perl supports two flavours of print(), one with the filehandle and the other without it (in which case it defaults to STDOUT).

        When perl "sees" $_->[0], it assumes that the latter flavour is in force, and by the time it arrives to "moo\n" it's expecting to find an operator (e.g. a comma, or a concatenation dot, or whatever). On the other hand, using the block resolves this ambiguity towards the former print() flavour.

        Flavio
        perl -ple'$_=reverse' <<<ti.xittelop@oivalf

        Don't fool yourself.

        I may have overheard most of a conversation stating that print is actually done as an indirect function call on a bareword (with magic to allow it to work)

        then again, i could have made it all up...

        the prin { $_->[0] } @foo we're seeing here is a block returning a file handle for print to write to (as perldoc says), so it's not a de-reference as *{ ... } would suggest

        Update: added some actual information

        @_=qw; ask f00li5h to appear and remain for a moment of pretend better than a lifetime;;s;;@_[map hex,split'',B204316D8C2A4516DE];;y/05/os/&print;

        Think of them all as blocks returning a value (the block { $h } is returning a hashref, which is then dereferenced by %); this particular instance just happens to be un-sigiled because you don't normally need a sigil on the filehandle slot argument anyhow.

        perldoc -f print:
        Note that if you're storing FILEHANDLES in an array or other expression, you will have to use a block returning its value instead:
        print { $files[$i] } "stuff\n"; print { $OK ? STDOUT : STDERR } "stuff\n";