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

I'm modifying a program which uses IPC::Open3::open3 to fire up mysql and query the database. What I don't understand is when they write to the "filehandle" created they put curly braces around the whole variable name like this:
print {$write_fh} "$database_query";
I know ${write_fh} would simply be a way to be explicit about the variable name, but I do not know what it means to put the whole name in curly braces like {$write_fh}. What does that indicate? Any input would be greatly appreciated!

Replies are listed 'Best First'.
Re: curly braces around a lexical file handle
by toolic (Bishop) on May 31, 2010 at 02:05 UTC
    The curly braces indicate a block. In your case, the curly braces are optional. But, in more complex cases, they are necessary. From the docs for 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
      In your case, the curly braces are optional.

      This is also a PBP-ism (#136). The general idea is always to do things in the same way even when unnecessary so no extra thought is needed (and no risk of forgetting is run) when it is necessary to do them in an unusual way.

      E.g., if you always write
          print {$filehandle} $some_data;
      even when you don't have to, no extra thought is needed when it comes time to write
          print {$hashref->{other}{handle}} $other_data;
      instead.

      Whether or not this approach is warranted in all cases is the subject of some debate.

        If that's true, you should be writing

        print( { $filehandle } $some_data );

        Running into problems from omitting those parens is far more likely than running into problem from omitting those curlies. Furthermore, omitting the curlies around the file handle expression when it's needed is likely to result in a compile-time error, whereas omitting parens can fail silently and subtly.

        If the argument you posted is valid, then it's far more important for

        print $filehandle $some_data;
        to be written as
        print($filehandle $some_data);
        than for it to be written as
        print { $filehandle } $some_data;
Re: curly braces around a lexical file handle
by ikegami (Patriarch) on May 31, 2010 at 03:55 UTC
    A few functions take an expression in curlies as their first argument:
    map ( { ... } ... ) grep ( { ... } ... ) print ( { ... } ... ) exec ( { ... } ... ) system ( { ... } ... )

    In print's case,

    • The expression in the curlies must result in the file handle to which print writes data.
    • In a few special circumstances (including a plain scalar), the curlies around the expression can be omitted.
    • The entire expression can be omitted in which case the data will be sent to the previously selected handle (normally STDOUT).

    In other words,

    print $write_fh "$database_query";
    is a shortcut for
    print { $write_fh } "$database_query";
      Interestingly, in all cases, either the block is optional, or there's an alternative, non-block syntax:
      map EXPR, LIST; grep EXPR, LIST; print LIST; print BAREWORD LIST; print $HANDLE LIST; exec STRING; exec LIST; system STRING; system LIST;
      And some you missed, also have a non-block syntax:
      sort BLOCK LIST; sort SUBNAME LIST; sort LIST; eval BLOCK; eval STRING;
      Not sure whether there's a common issue behind this, or that it's just a coincidence.
        You missed do (which has a non-block syntax as well).
      Odd that the few special circumstances seem to be the vast majority of uses ;)
        I suspect that's exactly why they are special.
Re: curly braces around a lexical file handle
by eyepopslikeamosquito (Archbishop) on May 31, 2010 at 02:40 UTC

    This style is recommended in Perl Best Practices, Chapter 10 (I/O), p. 217, Printing to Filehandles: "Always put filehandles in braces within any print statement".

    The idea is that putting braces around the filehandle helps it stand out clearly and clarifies your intentions in that you really did intend it to be treated as a filehandle and didn't just forget a comma.

      IMHO it's not just about forgetting the comma. When you write it with or without comma, two very different things look very similar.

      The additional curlies add "visual weight", one sees immediately that

      print $a, $b; # and print { $a } $b;

      do different things.

      I don't usually use the curlies, but that's more a result from laziness and thoughtlessness than anything else.

      I kinda like the Perl 6 way of doing it:

      print $a, $b; # print both variables $a.print: $b; # treat $a as a file handle

        That's not a realistic example. If you were printing two variables, it would look like

        print $name, ", ", age;
        or
        print "$name, age";

        And neither looks similar to the following to me:

        print $fh $age;

        As for your Perl6 eaxmple, you can do the same in Perl5.

        $fh->print($s); # Perl5 $fh.print: $s; # Perl6
        $a.print: $b;   # treat $a as a file handle
        Good thing you added the comment. I would have taken $a.print to mean the value of $a is to be printed out -- probably to handle $b.

      If you pass a file handle to print, the default assumption is that you want to print to the file handle. Adding curlies doesn't change anything.

      The reasoning you posted only makes sense if one assumes the file handle is badly named. The fix for a bad variable name is not to add silly curlies to print, it's to change the variable's name.

Re: curly braces around a lexical file handle
by graff (Chancellor) on May 31, 2010 at 18:17 UTC
    I appreciate the clearly-stated question about print, and the very informative replies it inspired, but I had to wonder about this bit in the OP:
    I'm modifying a program which uses IPC::Open3::open3 to fire up mysql and query the database.

    I wonder if it might be easier to just use DBI (which, if told to connect to a mysql database, will automatically use DBD::mysql).

      Thanks to all for these wonderful responses. Not only am I reassured that I'm not doing something weird without knowing it, but I feel like I understand several other things better, as well :-)

      btw the reason I can't use DBI is because the script is intended to run on "foreign" machines where we may not have the luxury of installing modules (and we're doing fairly simple queries as well).

        btw the reason I can't use DBI is because the script is intended to run on "foreign" machines where we may not have the luxury of installing modules (and we're doing fairly simple queries as well).
        But you do have the luxury of installing programs?

        What's the difference? What if you call DBI a program, is it then allowed to be installed?