3

Some time ago, I ask a question: How do I redefine built in Perl functions?

And the answers have served me well. I have a package that overrides Perl's 'open' function enabling me to log file access.

Now I've come to a case that breaks the functionality of the original code.

use strict;
use warnings;
use Data::Dumper;

sub myopen (*;@) {
  my $p;
  my $retval = CORE::open($p, $_[1]);
  {
    no strict;
    *{"main::$_[0]"} = $p;
  }
  return $retval;
}

BEGIN {
  *CORE::GLOBAL::open = *myopen;
};

my @a = (1, 2, 3);

open(CHECK, ">dump") or print "UNABLE TO OPEN DUMPER FILE: $!\n";
print CHECK "test\n";
print CHECK Data::Dumper->Dump(\@a);
close CHECK

Now I get this message:

Can't locate object method "CHECK" via package "Data::Dumper"

How do I fix it?

Community
  • 1
  • 1
mmccoo
  • 8,386
  • 5
  • 41
  • 60
  • If that's the complete error, it's using indiirect object syntax on the wrong object. Try CHECK->print( ... ) and see if you get the same error. – Anonymous May 02 '09 at 00:18

3 Answers3

8

Try using a name other than "CHECK".

"CHECK" is a special function which is called during compile time, and you really shouldn't use it.

$ open CHECK , '<', 'foo.txt'; 
Took 0.00224494934082031 seconds.

Runtime error: Undefined subroutine &Devel::REPL::Plugin::Packages::DefaultScratchpad::CHECK called at (eval 329) line 5.

$ open CHECKS , '<', 'foo.txt'; 
Took 0.00155806541442871 seconds.

$

Why that specific error?

perl -MO=Deparse -e 'print CHECK Data::Dumper 1';
print 'Data::Dumper'->CHECK(1);

Also, you're using global file handles, which are problematic.

use this notation:

open my $fh, '<' , $foo ; 
print <$fh>;
close $fh;

These are extra beneficial is they self-close when they go out of scope.

Kent Fredric
  • 56,416
  • 14
  • 107
  • 150
  • +1, nice analysis of the problem and you proposed the right solution (open()'s saner 3-arg syntax, with the filehandle in a lexical variable). And, I HATE PERL FOR THINGS LIKE THIS. – j_random_hacker May 02 '09 at 16:46
  • 3
    @j_random_hacker: Using PerlCritic will bring some Perl love back ;-) – draegtun May 03 '09 at 09:10
  • @draegtun: Perl::Critic looks interesting (though I fear what it will say about my large codebase of old, old code... :) ) – j_random_hacker May 05 '09 at 12:29
1

Compare:

> perl -MData::Dumper -e'local*_=*STDOUT;print _ Data::Dumper->Dump([2]);'
Can't locate object method "_" via package "Data::Dumper" at -e line 1.

to

> perl -MData::Dumper -e'local*_=*STDOUT;print _ ( Data::Dumper->Dump([2]) );'
$VAR1 = 2;

I used a different name from "STDOUT" because it seems to only gets the indirect object wrong when it's not a built-in handle.

Anonymous
  • 49,213
  • 1
  • 25
  • 19
1

This will work and without producing the error...

 print {*CHECK} Data::Dumper->Dump(\@a);

This stops it being confused has an "Indirect Object Syntax"

However I do recommend steering clear of using CHECK and other special named code blocks in Perl and using lexical variables for filehandles is the preferred method. PBP

AndyG
  • 39,700
  • 8
  • 109
  • 143
draegtun
  • 22,441
  • 5
  • 48
  • 71