in reply to Importing Time::HiRes::time at run-time (and failing)

because time is not a function but a built-in operator.

When perl compiles your function, it checks if time has been redefined in the current package and if so, it emits opcodes to call a subroutine called "time", otherwise, it emits the time opcode (pp_time). As you are defining time after compilation, the time call is being compiled as the built-in and so the function from Time::HiRes never gets called.

You can work around it as follows:

sub new { require Time::HiRes; return bless { t => Time::HiRes::time() }, 'P' }

Replies are listed 'Best First'.
Re^2: Importing Time::HiRes::time at run-time (and failing)
by grinder (Bishop) on Apr 20, 2006 at 15:10 UTC

    Aha! Thanks for the cogent explanation. Along with some advice from bart on the chatterbox, I came up with the following proof-of-concept solution.

    #! /usr/local/bin/perl -l package P; sub new { my $class = shift; my $mod = shift; eval "use $mod ()"; my $self = {}; if ($@) { $self->{_time_func} = sub { time }; } else { $self->{_time_func} = sub { Time::HiRes::time() }; } return bless $self, 'P' } package main; my $p = P->new( shift || 'Time::HiRes' ); print $p->{_time_func}->(); sleep 2; print $p->{_time_func}->();

    You can run this, and if T::HR is installed, you get fractional times. Pass it junk on the command line, and then T::HR is not loaded (which simulates what happens on an installation that lacks it, or fails to load) and integer seconds come out.

    In the real world, the _time_func business will be hidden from the user, they just get back fractional seconds, or not.

    • another intruder with the mooring in the heart of the Perl

      you can simplify it a bit replacing the eval "..." by a eval {...} and returning a reference to Time::HiRes::time instead of it wrapped inside an additional sub:
      package P; sub new { my $class = shift; my $self = {}; $self->{_time_func} = eval { require Time::HiRes } ? \&Time::HiRes::time : sub { time() }; bless $self, $class }