Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

RFC: feature proposal re code in @INC

by blazar (Canon)
on Jan 26, 2006 at 11:47 UTC ( [id://525698]=perlmeditation: print w/replies, xml ) Need Help??

Premise

One of my favourite 'tricks'1 is the possibility of putting code in @INC, as explained in perldoc -f require. Now, the standard way to use it is to return an open filehandle to the wanted module, e.g.

#!/usr/bin/perl use strict; use warnings; use lib sub { my $wanted=pop; return undef if $wanted ne 'Foo.pm'; open my $fh, '<', \<<'.EOM' or die "D'Oh! $!\n"; # ---- Begin package code. use strict; use warnings; package Foo; use base 'Exporter'; our @EXPORT='bar'; sub bar { print "Hmmm, seems to work!!\n"; } 1; __END__ .EOM # ---- End package code. $fh; }; use Foo; bar; __END__

(Although in this form looks more like obfuscation than a Good Thing™ ;-)

The proposal

Now, it occurred to me that even if, as usual, there are many other ways to do what I'm about to propose, one may want to use this feature to "alias" a package (or better, a set of packages at a time) by modifying $_[1] (in the case of the sub or array form of this 'trick') - and returning undef to let the default mechanism continue the search in the standard locations. But this is not currently possible:

$ perl -le 'use lib sub {$_[1]="Foo.pm"; undef}; use Anything;' Modification of a read-only value attempted at -e line 1. BEGIN failed--compilation aborted at -e line 1.

So I wonder if $_[1] could be made not read-only instead.

I understand that there may be inherent risks in doing so, but

  1. I don't see many options for one to inadvertently modify $_[1];
  2. the rationale should be that this is a somewhat "advanced" anyway so if one is using it, then he's supposed to know what it's doing.

1 See e.g.:

Replies are listed 'Best First'.
Re: RFC: feature proposal re code in @INC
by diotalevi (Canon) on Jan 26, 2006 at 14:44 UTC

    Try this. It does something but I'm not sure what.

    @_ = ( $_[0], "Whatever.pm" );

    PS, if you change the value from read-only, you'll probably be modifying the optree. That's usually a bad idea.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      I'm not sure if I understand your proposal, which is probable, given your hacking skills. However I don't want to force $_[1] to hold "Whatever.pm" for use in the same sub - I want it to be modified as a side-effect of the sub having been called, and I don't want to change the value from read-only either: I "want" it not to be read-only in the first place.

      I was thinking of something along these lines: suppose that one writes some modules in different versions for some different OSen (OK: as I premised since the beginning, I know there are other ways to do this), well if she had this feature available then she may do something like:

      use lib sub { for (qw/Foo.pm Bar.pm Baz.pm/) { if ($_[1] eq $_) { $_[1] =~ s/\./-$^O./; last; } } # let perl go on searching the 'faked' .pm! undef; };

      (There are probably better examples.)

      I admit that this opens an ambiguity as to what should be shown in case the modified module can't be found: is it, say, Foo.pm or Foo-linux.pm that can't be found? Probably, both, I would say: the error message may report both the original name and the "current" (at failure time) one, if they differ.

        I can imagine that someone could come up with a good way to use this feature. For example, in chaining with other code refs. I'm not entirely sure how that would work, but someone might be able to get it to work.

        However, I'm pretty sure this particular example would breed nothing but headache and heartache - there is no fallback mechanism here to allow you to say that if Foo-linux.pm doesn't exist, Foo.pm will be fine. Or, if it isn't fine, to print out a usable error message. Because as the user, I'd probably be confused by any error message referencing "Foo-linux.pm" when I had a "use Foo" in my code without some sort of extra information on my screen.

        Instead, I would suggest that code that is intended to stack probably should be made into objects that have an INC method (see require). Someone may write a generic "extract from tarball" INC object. If you want to change the name you get from the tarball, you can write your own INC object that wraps the tarball INC object, and changes the name on the way through.

        (Note that before looking this up during the writing of this node, I wasn't even aware of INC objects...)

        Gawds. Use some mundane magic for once. This @INC hackery sucks when used for things like this. Instead of "crecent wrench" you're pulling out the "hyper-spacial quantum vortex thingie with extra nubbly attachment." I loathe your example.

        BEGIN { eval "use Foo-$^O; 1" or die $@; }

        ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://525698]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (1)
As of 2024-04-25 00:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found