CV in @INC

geoff on 2002-01-16T16:31:23

did you know that you can store a coderef in @INC?

so, I went to dinner with my friend jeff so that we can have our semi-regular gripe session about the pains of authorship (he's working on a sysadmin book). anyway, we start talking about extproc_perl and he mentions that he is trying to solve some performance issues. apparently, the holy grail of extproc_perl is to be able to create indexes in Oracle using perl regular expressions (wow). anyway, apparently, through some coverstations with Tim Bunce, it was suggested that perhaps using the coderef-in-@INC hack might be able to help.

now, I'm not sure what the two of them were talking about, but jeff sent me this link and I poked around the threads some. now my mind is racing. this is sooooo cool.

seems like, among other things, you could have all pure-perl modules on some website and *poof* no more distribution problems. damn, that's cool. barrie slaymaker mentioned on #axkit the possibility of a CPAN.pm plug-in that installed a library if it couldn't be require()d. ok, so it's a bit crazy, but I'm a firm believer in the "if you build it, they will come" approach to programming.

hmph. wonder if I'll find the time to play with this...


It's Been Done

chromatic on 2002-01-16T18:30:16

Abigail demonstrated this on Perlmonks a while back. You can find The::Net in Abigail's CPAN directory, too. It does exactly what you suggest.

Re:It's Been Done

geoff on 2002-01-16T19:05:32

excellent!

thanks for the link. I just can't keep up these days.

Re:It's Been Done

pudge on 2002-01-16T22:19:51

Bah. I just found a bug of sorts. In pp_ctl.c, there is this:

    if (PERL_FILE_IS_ABSOLUTE(name)
    || (*name == '.' && (name[1] == '/' ||
                 (name[1] == '.' && name[2] == '/'))))
    {
    tryname = name;
    tryrsfp = doopen_pmc(name,PERL_SCRIPT_MODE);
    }
    else {

Now, the code to call the coderef only happens in the else. So if the file is determined to be absolute, but it is *not* able to be opened, then the coderef is never called. Try requiring something like "/foo" or "./foo", your coderef won't get called.

I ran into this because the Mac OS equivalent treats "http://foo/bar.pm" as an absolute path, so PERL_FILE_IS_ABSOLUTE(name) returns true, so the coderef is never called.

Bah, I say! Any thoughts?

Re:It's Been Done

chromatic on 2002-01-17T01:47:53

There are a couple of possibilities. Paths with leading protocol designations obviously don't mean the same thing with regard to "absolute" or "relative" paths. There could be another conditional to see if it looks like a local filesystem filepath -- if not, it punts to a coderef.

Another option is to say that URIs obviously aren't absolute in any sense that matters, though that conflates two slightly-different uses of the word. (The Mac behavior you describe seems wrong to me, but I've been known to be wrong at times.)

Re:It's Been Done

pudge on 2002-01-17T02:19:36

The Mac behavior's not wrong; if you have a volume "http" you could have a file "//foo/bar.pm", and it would be "http://foo/bar.pm".

But I think it would be Wrong to try to special-case URIs; having coderefs in @INC shouldn't be purpose-specific. What if I want to remove all the actual paths in @INC and handle everything via some custom handler? e.g., maybe if it is a Slash module I'll try to get it from my /usr/local/src/slash/ directory, otherwise look in /usr/local/lib/.

And if that is the case, if the right thing to do is to call the coderef if that is the only thing in @INC ... then the check for absolute paths should be skipped altogether. Yow.

This thing is really a hack, and it shouldn't be. I think it might be time to bring it to p5p for a bit of discussion.

Re:It's Been Done

geoff on 2002-01-17T14:57:46

heh, so these journals really are good for something :)

Other uses of coderef in @INC

pdcawley on 2002-01-16T19:53:50

I use the coderef-in-@INC trick, along with various nasty things involving local $INC{$package}, closures and evaling stuff with the expectation that it'll fail to get at package scoped lexicals in the refactoring engine I've been working on.

It's one of those hacks that seems at once utterly fantastic whilst at the same time being totally bloody evil.