Hi Monks, my first post here; I've been lurking for some time, ever since I became a perl coder. I ran across something interesting today in the behavior of seek on a tied filehandle that I could not find in any documention or discussion on this wonderful site. A little background: I wrote a tied filehandle module to return records of binary science data. The records are indexed by time, so my SEEK function naturally accepts a time value; a *floating-point* time value: since the data are accumulated on millisecond scales. But things were not right; the seeks went awry. Why?

Because 'seek' is a perl function that magically accesses my own SEEK subroutine, but which *always* coerces its second argument (the first is the fh) to an integer! Do you doubt this? See the code below!

(btw: I fixed my little problem by multiplying the times in the argument list by 1000 and then dividing by same within SEEK.)

- GRR
#!/usr/bin/perl use strict; package myNull; sub TIEHANDLE { my $class = shift; my $fh = local *FH; bless \$fh, $class; } sub SEEK { my $class = shift; my $offset = shift; my $whence = shift; print "SEEK: offset = $offset\n"; } 1; perl -e 'use myNull; tie *null, "myNull"; seek null, 5.5, 0;' SEEK: offset = 5

Replies are listed 'Best First'.
Re: Interesting SEEK behavior on tied filehandle (others)
by tye (Sage) on Aug 02, 2006 at 20:13 UTC

    Many tie methods force their arguments into more regular forms. You can't get anything but non-negative integers for indices into tied arrays ($x[-1] calls $obj->FETCH( $obj->FETCHSIZE() -1 ), for example). You can't use nor return a list where you would usually have a scalar. And so on...

    An exception appears to be that you can get more than just the string value for keys passed to tied hashes (and I suspect this was not always the case).

    - tye        

      I thought I might be able to pass a negative number to FETCH if the index was negative and bigger than the number of elements.

      Turns out FETCH is not even called in that situation, even though FETCH *is* called for indexes greater than the highest existing index.

      use Tie::Array qw( ); our @ISA = 'Tie::StdArray'; sub FETCH { my ($self, $idx) = @_; warn("Fetching index $idx\n"); return $self->SUPER::FETCH($idx); } my @a; tie @a, __PACKAGE__; $#a = 4; my $s; $s = $a[-@a+1]; # Fetching index 1 $s = $a[-@a]; # Fetching index 0 $s = $a[-@a-1]; # FETCH not called! $s = $a[@a]; # Fetching index 5

      Perl 5.6.1 & 5.8.6

Re: Interesting SEEK behavior on tied filehandle
by runrig (Abbot) on Aug 02, 2006 at 19:20 UTC
    I noticed an interesting behavior with the READ function when you called read() on a tied filehandle. Since read() accepts 3 or 4 arguments, the code I was looking at (not mine) went something like:
    sub READ { if ( @_ == 3 ) { # read into buffer } else { # read into buffer at offset }
    It turned out that even if you called read() with 3 arguments, READ was always called with 4 arguments, and the 4th (the offset) was set to zero (which I admit makes sense, but it threw a warning about uninitialized value in substr in this particular case, and made the conditional pointless).
Re: Interesting SEEK behavior on tied filehandle
by Fletch (Bishop) on Aug 02, 2006 at 19:11 UTC

    Call with an integer offset in ms rather than a float in seconds. Problem, if not solved, worked around fairly easily. :)