http://www.perlmonks.org?node_id=919359

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

Hello, Monks!

Is there any way to override "file test operator", using package?

I mean -X one - http://perldoc.perl.org/functions/-X.html

if (-e($file_name)) {}

It's more than easy to override lot of over functions, using "sub FUNCTION_NAME { }" inside package, but i have no idea what sub name I could use to override "file test operator"? (it's even hard to name correctly here, to ask that question).

Any reply would be welcome, so I could at least stop searching.

Replies are listed 'Best First'.
Re: Is there any way to override "file test operator"?
by kejohm (Hermit) on Aug 09, 2011 at 02:38 UTC

    You can overload the operator with the overload pragma, although this only works if your package is being used as a class. Also only works on Perl v5.12 or later. Example:

    package MyFileTest; use overload ( '-X' => \&myfiletest, ); sub new { ... } ... package main; my $file = MyFileTest->new($filename); if(-f $file){ ... }

    See also the filetest pragma.

      Hmm, then this should also work, but it doesn't
      #!/usr/bin/perl -- BEGIN { use IO::File; package IO::Handle; use overload '-X' => sub { warn 'abracadabra'; stat@_; }; *IO::Handle::stat = sub { warn "hi walter"; stat(@_); }; } open my($fh), '<', __FILE__; print '-e ', -e $fh, "\n"; print '-f ', -f $fh, "\n"; print '-d ', -d $fh, "\n"; print 'stat ', stat $fh, "\n"; print $fh, "\n"; close $fh; print "$_\n" for keys %INC; __END__ -e 1 -f 1 -d stat 00332061000745131287651313128765131312876169 GLOB(0x3f8adc) warnings/register.pm XSLoader.pm IO/Handle.pm SelectSaver.pm IO/Seekable.pm warnings.pm Fcntl.pm IO.pm Symbol.pm Carp.pm File/Spec/Unix.pm strict.pm Exporter.pm vars.pm File/Spec.pm IO/File.pm overload.pm File/Spec/Win32.pm
Re: Is there any way to override "file test operator"?
by Marshall (Canon) on Aug 09, 2011 at 02:31 UTC
    WHAT?

    if (-e($file_name)) {};
    Trying to override the -e file test is not what I would consider "smart". Even if you could, this is a bad idea.

    What other meaning would you have the "-e" do? And why would it make sense in the code?

      And I - as a simple bystander - would read that as

      if ( - e ($filename)) { ^

      that is "the negative value returned by the function e with argument $filename".


      Enjoy, Have FUN! H.Merijn
        #!usr/bin/perl -w use strict; my $file = 'C:\temp\test20.pl'; if ( -e $file) { print "$file EXISTS!\n"; } print "$0 \n"; if ( - e $file) #this does not work! { print "$file WILD!\n"; } __END__ Can't locate object method "e" via package "C:\temp\test20.pl" (perhaps you forgot to load "C:\temp\test20.pl"?) at C:\TEMP\test20.pl line 13. C:\temp\test20.pl EXISTS! C:\TEMP\test20.pl
      Even if you could, this is a bad idea.
      Such a blanket statement, without knowing the reasons of the OP needs at least some justification to be taken seriously.
      Why can't the OP decide to make a smarter file test operator? Maybe instrument it, or log something, or count gumdrops? Or maybe he has a new file system idea, where there are virtual files, and they only show up with special juju magic? Or an evil twin has renamed some files with a specific pattern, and the code needs to test for both possibilities?

      Sure, outside of that, it's probably not a good idea.

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

        I read back through this thread. Now that I see it again, the question appears to be "how can I make new file test operator?".
        I don't know how to do that.

        Overriding an existing file operator (like: -e $filename) is very bad idea. I stick to that opinion. The issue is when I see a line like that in some huge amount of code, I expect -e to do what it normally does without having to read any previous code that redefined that operation. And BTW, I don't know how to redefine -e either.

        In this case, I would make a subroutine that did the desired test and use that. In terms of execution efficiency, I see no difference. In terms of source code, there would be a huge increase in clarity.

Re: Is there any way to override "file test operator"?
by JavaFan (Canon) on Aug 09, 2011 at 08:24 UTC
    I don't think you can, at least not on a pure Perl level. If you're willing to write -E, or - e, you can write a subroutine named E or e, which then will be called instead (and of whose return value unary minus will be applied).
Re: Is there any way to override "file test operator"?
by Anonymous Monk on Aug 09, 2011 at 08:09 UTC

    Um, why would you even want to do this? You want to lie to your program about whether a file exists or not? Without some pretty specific and esoteric reasons, that just sounds silly

      One use I could see for this would be filenames that refer to a virtual file system. For example -f 'smb://server/share/file.name' or -r 'ssh:user@host:some/file' could be resource tests that make sense if you want to provide a different syntax than just local filenames.

      Another use-case is for testing, e.g. I have a test script that detects whether bash exists using -x "/bin/bash". I'd like to be able to simulate the absence of bash by returning false to that expression even though /bin/bash is actually on my filesystem.
      Another use case is implementing support for symlinks on Windows. See Win32::Links for a situation where someone has taken the effort to do so, and could use a means of supporting -l to make it seamless.