Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between \*DATA and *DATA

Tags:

perl

Whenever I want to simulate input and output to a filehandle, I'll often use references to DATA and STDOUT respectively:

use strict;
use warnings;
use autodie;

#open my $infh, '<', 'infile.txt';
my $infh = \*DATA;

#open my $outfh, '>', 'outfile.txt';
my $outfh, \*STDOUT;

print $outfh <$infh>;

__DATA__
Hello World

Outputs:

Hello World

However, in a recent answer by Borodin, it was demonstrated that it's not actually necessary to take a reference. Instead, a simple assignment is sufficient:

my $infh = *DATA;

I therefore created the following script to compare and contrast the difference between these two methods:

use strict;
use warnings;

use Fcntl qw(:seek);

# Compare Indirect Filehandle Notation
my %hash = (
    '\*DATA' => \*DATA,
    '*DATA'  => *DATA,
);

my $pos = tell DATA;

my $fmt = "%-8s %-22s %-7s %s\n";
printf $fmt, qw(Name Value ref() readline());

while ( my ( $name, $fh ) = each %hash ) {
    seek( $fh, $pos, SEEK_SET );    # Rewind FH
    chomp( my $line = <$fh> );
    printf $fmt, $name, $fh, ref($fh), $line;
}

__DATA__
Hello World

Outputs:

Name     Value                  ref()   readline()
\*DATA   GLOB(0x7fdc43027e70)   GLOB    Hello World
*DATA    *main::DATA                    Hello World

When it comes to passing and reading from the filehandle, there appears no difference between a typeglob and a reference to a typeglob.

Switching from testing to the research form of investigation reveals the following perldoc pages:

  • perldata - Typeglobs and Filehandles
  • perlfaq5 - How can I use a filehandle indirectly?

The first reference suggests either usage. While the second gives a list of other alternatives as well, but mentions how the reference notation is needed if we want to bless the variable. No other difference is suggested.

Is there a functional or preferred style difference these two indirect filehandles?

  1. my $fh = \*DATA;
  2. my $fh = *DATA;
like image 825
Miller Avatar asked Sep 10 '14 23:09

Miller


1 Answers

One's a glob; one's a reference to a glob. Most places accept both. Many also accept the name of the glob as a string, and many accept a reference to an IO object.

# Symbolic reference to the glob that contains the IO object.
>perl -E"$fh = 'STDOUT';    say $fh 'hi'"
hi

# Reference to the glob that contains the IO object.
>perl -E"$fh = \*STDOUT;    say $fh 'hi'"
hi

# Glob that contains the IO object.
>perl -E"$fh = *STDOUT;     say $fh 'hi'"
hi

# Reference to the IO object.
>perl -E"$fh = *STDOUT{IO}; say $fh 'hi'"
hi

open(my $fh, '<', ...) populates $fh with a reference to a glob, and it's the most supported, so that's what I use if I have to choose.

like image 178
ikegami Avatar answered Oct 05 '22 18:10

ikegami