Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Compare CODE

by PetaMem (Priest)
on Dec 11, 2012 at 11:22 UTC ( #1008270=perlquestion: print w/replies, xml ) Need Help??
PetaMem has asked for the wisdom of the Perl Monks concerning the following question:


Given two coderefs. Is there an (elegant) way to compare the code they're pointing to?

No, I don't need any fancy stuff like solving the halting problem. ;-) I do not even need to know if the code is equivalent. It would be completely sufficient if these

my $cr1 = sub { $foo = $bar * $baz; } my $cr2 = sub { $foo = $bar * $baz; }

Would be considered "same". Ideally with the whitespaces being irrelevant. All mutations, invariants etc. can safely be considered 'different'. i.e.

my $cr3 = sub { $mul = $op1 * $op2; } my $cr4 = sub { $foo = $baz * $bar; }

To sum up: It would be sufficient to have a function that - for two given coderefs (pointing to different addresses) - would just return "identic" if they'd be the same list of opcodes.

Howto? B:: something?

Thank you for your guidance.

    All Perl:   MT, NLP, NLU

Replies are listed 'Best First'.
Re: Compare CODE
by Athanasius (Chancellor) on Dec 11, 2012 at 11:44 UTC

    I think you pretty much answered your own question: B::Deparse seems to do just what you want:

    #! perl use Modern::Perl; my ($foo, $bar, $baz, $mul, $op1, $op2); my $cr1 = sub { $foo = $bar * $baz; }; my $cr2 = sub { $foo = $bar * $baz; # Note whitespace differences }; my $cr3 = sub { $mul = $op1 * $op2; }; my $cr4 = sub { $foo = $baz * $bar; }; compare_subs($cr1, $cr2); compare_subs($cr3, $cr4); sub compare_subs { my ($s1, $s2) = @_; use B::Deparse; my $deparse = B::Deparse->new("-p", "-sC"); my $body1 = $deparse->coderef2text($s1); my $body2 = $deparse->coderef2text($s2); if ($body1 eq $body2) { say 'Identical'; } else { say 'Different'; } }


    21:39 >perl Identical Different 21:40 >

    So, the initial results look promising, at least!

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      The only problem is closed-over variables...

      use strict; use warnings; use B::Deparse; sub make_multiplier { my $n = shift; return sub { $n * $_[0] }; } my $double = make_multiplier(2); my $treble = make_multiplier(3); print "double and treble clearly do different things...\n"; print "double 5: ", $double->(5), "\n"; print "treble 5: ", $treble->(5), "\n\n"; my $deparse = B::Deparse->new; $deparse->ambient_pragmas(strict => 'all', warnings => 'all'); print "yet, here is the B::Deparse output for double...\n"; print $deparse->coderef2text($double), "\n\n"; print "and here is the B::Deparse output for treble...\n"; print $deparse->coderef2text($treble), "\n"; __END__ double and treble clearly do different things... double 5: 10 treble 5: 15 yet, here is the B::Deparse output for double... { $n * $_[0]; } and here is the B::Deparse output for treble... { $n * $_[0]; }
      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1008270]
Approved by Ratazong
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2018-01-21 02:12 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (227 votes). Check out past polls.