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

I'm looking at PBP, the I/O chapter, regarding printing to indirect filehandles.

What exactly does the {$fh} in

open my $fh, '>', 'foo.txt' or die "Ouch. $!"; print {$fh} "hi!\n"; close $fh;
evaluate to? Because the docs for print say that it can take a filehandle there, but AFAICT, {$fh} is a wee little block (and not a filehandle), right?

Replies are listed 'Best First'.
Re: blocks and using braces around filehandles with print
by ikegami (Patriarch) on Mar 16, 2008 at 04:21 UTC

    print $fh LIST;
    and
    print { $fh } LIST;
    are equivalent.

    The curlies are required when dealing with more complex expressions for the file handle.

    >perl -e"my @h = ( \*STDOUT ); print $h[$_] qq{foo!\n} for 0..$#h" syntax error at -e line 1, near "] qq{foo!\n}" Execution of -e aborted due to compilation errors. >perl -e"my @h = ( \*STDOUT ); print { $h[$_] } qq{foo!\n} for 0..$#h" foo!

      (Not my question, but thought I'd jump in:)

      So the rules here are the same as whether or not you need curlies for dereferencing an array (etc.)? e.g. @$arrayref but @{ $arrayrefs[0] } ?


      I'm a peripheral visionary... I can see into the future, but just way off to the side.

        There really isn't any connection between those two kinds of curlies. Those of which you speak act like parens to modify precedence and are solely used in dereferencing.
        $$array[0] # Short for ${ $array }[0] ${ $array }[0] # The first element of the array referenced by $array ${ $array[0] } # The scalar referenced by the first element of @array

        A third, similar type of curlies is used in interpolation to show where the variable name ends.

        "foo$varbar" # Equivalent to "foo" . $varbar "foo${var}bar" # Equivalent to "foo" . $var . "bar"
      The curlies are required when dealing with more complex expressions for the file handle.

      Right, but what I want to know is: what exactly does that thing with the curlies around it evaluate to? I think the problem is, I don't really understand what a BLOCK is.

        A block is 'code' in this case code that returns a file handle - see how perl deparse's the above code and puts a semicolon before the right curly brace in the code below:
        $ perl -MO=Deparse fh.pl
        die "Ouch. $!" unless open my $fh, '>', 'foo.txt'; print {$fh;} "hi!\n"; close $fh;
        fh.pl syntax OK
        (there are probably other methods that you can use to have perl show you what it is "thinking")
        perldoc -f print does mention the blocks
        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: print { $files[$i] } "stuff\n"; print { $OK ? STDOUT : STDERR } "stuff\n";

        A block contains 0 or more Perl statements. A block evaluates the the last value evaluated within the block.

        Examples:

        { STDOUT } -> STDOUT { $hash{$k}[$i] } -> $hash{$k}[$i] { my $x = func(); uc($x) } -> uc($x) { if ($cond) { 'FOO' } } -> If $cond is false, $cond. -> If $cond is true, 'FOO'.
Re: blocks and using braces around filehandles with print
by aquarium (Curate) on Mar 17, 2008 at 04:39 UTC
    just in case all those uses haven't already curled your curlies ;) you can also use them to scope variables or semi-hide them, and also to create anonymous subroutines.
    the hardest line to type correctly is: stty erase ^H