ninuzzo has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to do that as explained in the perlsub manpage and this blog, but wasn't able to get the first argument to the CORE::open.

Here's my code:

package MyOpen; require Exporter; @ISA = 'Exporter'; @EXPORT_OK = 'open'; use Carp; use Data::Dumper; sub import { my $pkg = shift; return unless @_; my $sym = shift; my $where = ($sym =~ s/^GLOBAL_// ? 'CORE::GLOBAL' : caller(0)); $pkg->export($where, $sym, @_); } sub open (*;$@) { print Dumper(\@_), "\n"; return CORE::open $_[0], $_[1], $_[2]; } 1;
When I use a lexical (open $file, ...) I get undef into $_[0]. It doesn't work with a typeglob (open FILE, ...) as well. I'm at my wits' end :(

Replies are listed 'Best First'.
Re: Override the open builtin globally
by moritz (Cardinal) on Jun 13, 2011 at 16:29 UTC
    When I use a lexical (open $file, ...) I get undef into $_[0].

    Well, if your calling code is something like

    my $file; open $file, ...

    then $file is undef, and open changes its value to be a file handle - but since you haven't called the core open() yet, you still see the undef.

Re: Override the open builtin globally
by ikegami (Patriarch) on Jun 13, 2011 at 16:27 UTC

    When I use a lexical (open $file, ...) I get undef into $_[0].

    Did you put a value into $file before passing it to open? Then why are you expecting something other than undef?

Re: Override the open builtin globally
by Khen1950fx (Canon) on Jun 13, 2011 at 19:47 UTC
    I think that you were after something like this:
    #!/usr/bin/perl use strict; use warnings; BEGIN { *CORE::GLOBAL::open = sub (*;$@) { if(defined($_[0])) { use Symbol qw(); my $handle = Symbol::qualify($_[0], (caller)[0]); no strict 'refs'; if(@_ == 1) { return CORE::open($handle); } elsif(@_ == 2) { return CORE::open($handle, $_[1]); } else { return CORE::open($handle, $_[1], @_[2..$#_]); } } }; }
    As I understand it, to override globally, you need to use CORE::GLOBAL in a BEGIN block because it has to be done at compile time.
      if(defined($_[0])) { ...

      You forgot to handle the case when $_[0] is undef, i.e. when the form open my $fh, ... is being used.

      BEGIN { *CORE::GLOBAL::open = sub (*;$@) { use Symbol (); my $handle = Symbol::qualify_to_ref($_[0], scalar caller); $_[0] = $handle unless defined $_[0]; # pass up to caller if (@_ == 1) { CORE::open $handle; } elsif (@_ == 2) { CORE::open $handle, $_[1]; } elsif (@_ == 3) { if (defined $_[2]) { CORE::open $handle, $_[1], $_[2]; } else { CORE::open $handle, $_[1], undef; # special case } } else { CORE::open $handle, $_[1], $_[2], @_[3..$#_]; } }; } # sample usage: open my $fh, ">", \my $buf or die $!; print $fh "hello"; print $buf; # prints "hello"
        Hi,

        Could you kindly advise about writing using dumper?

        The following open using last version:

        open(FILE,"> tmp.pm"); print FILE "blabla"; # works correctly #print FILE Dumper %tmp_hash; #works correctly print FILE Data::Dumper %tmp_hash; #fails: "Can't locate object metho +d "FILE" via package "Data::Dumper" "
        Any ideas/advises? since I would like to use specific pre defined Data::Dumper, which doesn't recognize the FILE.