Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Converting a coderef back to code

by oxone (Friar)
on Apr 24, 2009 at 12:03 UTC ( #759816=perlquestion: print w/replies, xml ) Need Help??
oxone has asked for the wisdom of the Perl Monks concerning the following question:

I am creating a module which takes various parameters, including coderefs. Since my module also does some internal cacheing of return values where parameters have been seen before, I am wondering if it's possible to 'stringify' a coderef in order work out if the module has seen it before. So for example:
my $coderef = sub{ return "Hello"; }; # Possible somehow to manipulate $coderef # here, to get back to the code itself?
I presume the answer is no, and that the scalar value of the coderef - eg. CODE(0x225c2c) etc. - is just a memory location of no use in this context as it may be different if code is the same, or indeed the same even if the code is different.

My planned workaround is for the module to accept code as string values instead of coderefs, and then 'eval' them into coderefs inside the module, but this doesn't seem very elegant.

Is there a better way?

Replies are listed 'Best First'.
Re: Converting a coderef back to code
by Bloodnok (Vicar) on Apr 24, 2009 at 12:21 UTC
    Try using coderef2text() from the B::Deparse module - the earlier suggestion to use the Deparse option from Data::Dumper rely on both
    • Your installed version of Data::Dumper supporting the given option (which you may not have the power or opportunity to change)
    • The code ref. being deparseable by B::Deparse - which Data::Dumper calls

    So just use B::Deparse anyway :-D

    Update:

    Looks like my post and oxones reply crossed in the post

    A user level that continues to overstate my experience :-))
Re: Converting a coderef back to code
by citromatik (Curate) on Apr 24, 2009 at 12:23 UTC
    I am wondering if it's possible to 'stringify' a coderef

    Yes, this is possible:

    my $stringify = B::Deparse->new->coderef2text($coderef);

    See Is it useful to edit code at execution time? for an example of what you are trying to accomplish (I'm happy to see that you will give a "yes" to that question). Also, the module Sub::Compose uses this technique.

    Hope this helps,

    citromatik

      Thanks! Just what I needed. I'm not actually going to edit or re-eval the code from the coderef, but getting it into string form means I can then work out whether the same code has been passed in before, such that a cached result can be returned. Conveniently, that means I also don't have to worry about the specific code formatting used by B::Deparse either :-)
Re: Converting a coderef back to code
by Anonymous Monk on Apr 24, 2009 at 12:09 UTC
    #!/usr/bin/perl -- use strict; use warnings; print oxone(\&oxone); sub oxone { use Data::Dumper; local $Data::Dumper::Deparse=1; return Dumper(shift); } __END__ $VAR1 = sub { use warnings; use strict 'refs'; local $Data::Dumper::Deparse = 1; return Dumper(shift @_); };
      Great - many thanks for the solution!

      I just went looking for how Data::Dumper does this, and it seems the core solution is:

      use B::Deparse; ... my $string = B::Deparse->new->coderef2text($coderef);

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://759816]
Approved by ww
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (2)
As of 2018-10-22 05:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When I need money for a bigger acquisition, I usually ...














    Results (119 votes). Check out past polls.

    Notices?