Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

how can I access code ref contents, not call it?

by knight (Friar)
on Jan 04, 2001 at 04:37 UTC ( [id://49659]=perlquestion: print w/replies, xml ) Need Help??

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

This is definitely off the beaten track, so it'll probably help if I start with why I want to do something this screwy.

I'm extending Cons, a Perl-based substitute for Make, to support generating a target file by calling a Perl code ref instead of an external command.

Cons will rebuild a target file if the file's build command changes. Cons tracks this by adding the command line into an MD5 signature for the target file. If the command line changes, the signature changes and the file gets rebuilt.

Ideally, this should work the same for code refs. If the Perl code used to generate a target file changes, the file should get rebuilt. So how do I figure out if the code changed since the last build?

What I'd like to do is be able to use the same MD5 signature mechanism on the "contents" of the code ref--maybe, for example, treat the compiled code as a byte string and generate an MD5 signature on that. Something like that would be cleanest for the Cons architecture, but the only things I can figure out to do with a code ref are:
# call it: $coderef->(); # not what I want, obviously # stringify it: "$coderef" # generates "CODE(0x8405f54)", e.g.
Note that I can't use the representation of the memory address itself, because that will likely be different each time Cons is run. If I knew how long the compiled code ended up being, I could theoretically generate the signature on N bytes starting at the supplied address, but I don't see how to do that, either.

If there isn't any magic that will let me at the compiled "contents" of a code ref in this way, my workaround will be to use the MD5 signature of the entire config file in which the ref appears. That would have the drawback, though, of forcing anything with a code ref to be rebuilt anytime the config file changes, so I'd be grateful for any suggestions about other ways to try to do this...

Replies are listed 'Best First'.
Re (tilly) 1: how can I access code ref contents, not call it?
by tilly (Archbishop) on Jan 04, 2001 at 05:36 UTC
    The simplest solution is likely to say that the Perl code must be passed as text to Cons. Then Cons will compile it into an anon sub and use that. (This is not totally different from, say, how CGI is written.)

    Alternately you can start staring at the various B::* and Devel::* modules to see if any will let you decode the guts of a subroutine into canonical form. I don't know of any, but I don't play much with that.

      I strongly second tilly's suggestion. Text is *the* portable medium for Perl code. If you have an eval(), why not use it.

      Christian Lemburg
      Brainbench MVP for Perl
      http://www.brainbench.com

        If you have an eval(), why not use it.

        Quoting.

        Creating a complex subroutine in text gets decidedly non-trivial and hard to maintain when you have to remember to not escape $foo because you want it interpolated but to escape \$bar because it's a local variable in your text's code. For many situations, a good old anonymous subroutine reads a lot cleaner.

        Cons actually already supports Perl code snippets in text, so this is an empirical observation. Both approaches do have their advantages and disadvantages. (Besides, providing both mechanisms would give people More Than One Way To Do It... :-)
Re: how can I access code ref contents, not call it?
by autark (Friar) on Jan 04, 2001 at 05:47 UTC
    With perl 5.6 you should be able to say:
    use B::Deparse; sub bar { print "foo" } my $deparse = B::Deparse->new(); my $body = $dep->coderef2text(\&bar); print $body;
    (See perldoc B::Deparse). This returns the coderef as plain text. Or you might use the B module via the O module to do some of the work yourself.

    Autark.

      If you try that, it is not reliable. In the case of closures there can be considerable context which you miss. Such as which variables are global and which are private lexicals, and in the latter case what are the values of said lexicals.

      There will be far fewer scoping games to cope with if you compile it yourself in a known scope.

Re: how can I access code ref contents, not call it?
by 2501 (Pilgrim) on Jan 04, 2001 at 05:56 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://49659]
Approved by root
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: (8)
As of 2024-04-18 10:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found