3

In trying to answer an old question in a clever way, I was going to attempt this, not knowing if it would succeed:

#!/usr/bin/env perl

use strict;
use warnings;

use Tie::File;
tie( my @data, 'Tie::File', \*DATA ) or die "Cannot tie DATA";

foreach ( @data ) {
    print;
}

foreach ( @data ) {
    print scalar reverse;
}


__DATA__
one
two
three
four
five
six

I expected it to either work, or die; what I got was unexpected:

#!/usr/bin/env perluse strict;use warnings;use Tie::File;tie( my @data, 'Tie::File', \*DATA ) or die "Cannot tie DATA";foreach ( @data ) {    print;}foreach ( @data ) {    print scalar reverse;}__DATA__onetwothreefourfivesixlrep vne/nib/rsu/!#;tcirts esu;sgninraw esu;eliF::eiT esu;"ATAD eit tonnaC" eid ro ) ATAD*\ ,'eliF::eiT' ,atad@ ym (eit{ ) atad@ ( hcaerof;tnirp    }{ ) atad@ ( hcaerof;esrever ralacs tnirp    }__ATAD__enoowteerhtruofevifxis

How on earth did attempting to tie __DATA__ into Tie::File did it tie the script, and chomp it too?!

Community
  • 1
  • 1
Joel Berger
  • 20,180
  • 5
  • 49
  • 104

1 Answers1

4

The DATA filehandle is just an open filehandle to the file that refers to it. It has some additional magic that the first time it is read from, it seeks to the first byte after the __DATA__ or __END__ token in your program, giving you the behavior you expect.

When you tie *DATA, you are getting in the way of the first-read magic, and getting a handle to your source file positioned at the top of the file.

I suspect that if you call tell DATA first (or maybe seek DATA,0,1) before you tie it, it will be in the correct position and "work" like you expected.

mob
  • 117,087
  • 18
  • 149
  • 283
  • 2
    Spot on. Also regarding the `chomp`, `Tie::File` does auto-chomping unless you tell it not to. – Eric Strom Oct 27 '11 at 20:48
  • The unbeatable tag team gets it quickly. This was a best a curiousity and at worst a bug. Thanks. – Joel Berger Oct 27 '11 at 21:15
  • The `tell` and `seek` on DATA don't help, but I'm sure that you have the problem nailed. I suspect that if you tie an open handle, which has been `seek`ed to the middle somewhere, that `Tie::File` first goes back the the beginning. – Joel Berger Oct 27 '11 at 21:19
  • @Joel Berger - you're right. There's a `seek $file,0,0` call early in `Tie::File`. Maybe that's worth a bug report? :-) – mob Oct 27 '11 at 21:54
  • @mob, hmmm, while I agree that this feels like there could be something better, I'm not sure what it would be. Is there some way to detect that the filehandle points to DATA, or some way to hook into DATA's magic. For testing `Tie::Array::CSV` I write to a `File::Temp` tempfile and then tie that handle. If there was some way to detect DATA perhaps it could be intercepted and used. Still its interesting to have pulled the covers off of the implementation of the `__DATA__` section here. – Joel Berger Oct 28 '11 at 13:27
  • Not sure why I thought of this lately, but it allows for a silly little quine: https://gist.github.com/2941467 – Joel Berger Jun 16 '12 at 14:25