Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: Syntax error when trying to use a hash value as a file stream specifier

by BillKSmith (Monsignor)
on Sep 02, 2022 at 20:36 UTC ( [id://11146643]=note: print w/replies, xml ) Need Help??


in reply to Syntax error when trying to use a hash value as a file stream specifier

The book "Perl Best Practices" (ISBN 0596001738) recommends that you always use braces around the file handle in a print statements to make it clear that you did not forget a comma. This practice would eliminate your problem as well.

Did you consider redirecting your default output with select rather than passing it as an argument?

UPDATE: I believe that the OP is passing a file-handle to a subroutine using the method that his reference (Cookbook recipe 10.7) calls 'Named Parameters'. Using this method, the file-handle is stored as a value in a hash. He as asking for the syntax to use that value in a print statement. AnomalousMonk has provided the answer. My suggestion to use select to pass the file-handle to the subroutine would work, but I no longer recommend it.

use strict; use warnings; myfunction1( handle => \*STDERR); sub myfunction1{ my %hash = ( handle => \*STDOUT, @_ ); print "something will happen\n"; print {$hash{handle}} "anything from myfunction1\n"; # ^ ^ # braces added here }
Bill

Replies are listed 'Best First'.
Re^2: Syntax error when trying to use a hash value as a file stream specifier
by afoken (Chancellor) on Sep 03, 2022 at 10:47 UTC
    Did you consider redirecting your default output with select rather than passing it as an argument?

    The handle is not passed as an argument, if it was, it would be followed by a comma. It is actually indirect object syntax (method $object @arguments in contrast to $object->method(@arguments)), see perlobj.

    Using select is a global operation, it switches the default handle for all write, print, and (not yet documented in select) say <Update>without an explicit handle</Update> from STDOUT (or whatever was previously selected) to the handle passed to select. This has consequences that may lead to unwanted features a.k.a. bugs:

    package Some::Third::Party::Module; # ... sub doSomething { say "This will take some time"; sleep 10; say "Done"; } # ...
    #!/usr/bin/perl # ... use Some::Third::Party::Module qw( doSomething ); # ... open my $h,'>:raw','output.bin'; my $oldSelected=select $h; print "\x00\x42\xAF\x99"; doSomething(); print "\x33\xFF\x81\x73"; select $oldSelected; close $h;

    Guess why output.bin is longer than expected and does not work as expected.

    Using the usual indirect object notation fixes the problem:

    open my $h,'>:raw','output.bin'; print $h "\x00\x42\xAF\x99"; doSomething(); print $h "\x33\xFF\x81\x73"; close $h;

    Of course, if you like the mental pain and want to get hurt by the future maintainer, you could also select handles as needed. Welcome back to the 1960s, when this was the only way to handle files in MUMPS:

    open my $h,'>:raw','output.bin'; my $oldSelected=select $h; print "\x00\x42\xAF\x99"; select $oldSelect; doSomething(); select $h; print "\x33\xFF\x81\x73"; select $oldSelected; close $h;

    I would not use select to globally switch file handles, not even for a short piece of code. It just causes way too much trouble.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      Good point! The function select acts as if it controls an anonymous global variable. That 'variable' has all the advantages and disadvantages of any global variable except that we cannot examine it. In your example, we all expect say to output to stdout. It is easy to forget that it may not be true.

      Until the documentation for say is corrected, the victim of this bug could certainly claim that the bug is in perl, not his code.

      Bill
        > we cannot examine it

        Of course we can:

        if (select eq 'main::STDERR') {

        > Until the documentation for say is corrected

        Done.

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11146643]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (None)
    As of 2024-04-25 00:12 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found