Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Print all derefs and method calls in a directory (Friday golf)

by jepri (Parson)
on Jan 09, 2009 at 04:45 UTC ( #735078=perlquestion: print w/ replies, xml ) Need Help??
jepri has asked for the wisdom of the Perl Monks concerning the following question:

I was trying to figure out what hashes were in some code. It was a new code base that I needed to become familiar with (no docs, naturally).

This command line does a pretty good job of making a hierarchical listing from the code. What would you do better?

rgrep -e'->' * | perl -ne '/(\S{3,80}->\S{5,80})/;print $1,"\n"' | pe +rl -pe's/^\(//' | perl -pe 's/^\+\+|^\-\-//' | sort | uniq | less

It only picks up -> derefs but everyone here (ed:at the office) seems to code that way, so it's a win for me.

ed2: I didn't give an example of the output, which ends up looking something like this:

... $people->{login}->{chair}->{color}=something $people->{login}->{chair}->{height}->(blah) $people->{login}->{chair}->{wheels} =~ etc $people->{login}->{desk}->{paperclips} $people->{login}->{desk}->{stapler} ...

Comment on Print all derefs and method calls in a directory (Friday golf)
Select or Download Code
Replies are listed 'Best First'.
Re: Print all derefs and method calls in a directory (Friday golf)
by ikegami (Pope) on Jan 09, 2009 at 04:57 UTC

    It only picks up -> derefs but everyone here seems to code that way, so it's a win for me.

    I don't believe that's true. I do

    for (@$list) { ... }

    and

    for (keys %$table) { ... }

    and

    $grid[$x][$y]

    regularly. I even do

    our $buf; local *buf = $ref;

    often enough. All of those contains derefs. Three of them aren't even possible to do with the arrow.

      Unless I'm missing something, the examples you have are fairly simply structured - I'm having to deal with calls like:
      $people->{login}->{chair}->{height}
      and each level is tampered with by a different module.

      So in your examples I'd be seeing: for (@{$people->{login}->{desk}->{paperclips}){}

        There are four derefences in

        @{$people->{login}->{desk}->{paperclips}}

        but only three arrows.

        The rest of your post doesn't relate to what I said, so I have no comment on it save that I rarely have paths that long.

        for my $employee (@$employees) { for my $desk (@{ $employee->{desks} }) { $paperclips += $desk->{paperclips}; } }

        Four dereferences, but only two arrows. And the output of your script doesn't illustrate the structure at all. Data::Dumper will do that to some extent.

Re: Print all derefs and method calls in a directory (Friday golf)
by JavaFan (Canon) on Jan 09, 2009 at 09:44 UTC
    It seems to miss cases like:
    $foo ->[2]; # Space before or after -> print $_->{bar}; # Only two non-space chars before -> $sum += $_->[0] for @array; # Only three non-space chars after ->
    And since you aren't using warnings, you don't get a warning if you try to print an undefined $1.

    OTOH, it would find a deref in:

    perl -ne '/(\S{3,80}->\S{5,80})/;print $1,"\n"'
    Don't tell me you never write code like that!

    But I'm baffled by the fact you're searching for '->' when you need to figure out which hashes are in some code.

      Assuming rgrep does what I thik it does, $1 will never be undef since he pre-filters the lines.

      (Nevermind, the patterns are different, so it's possible.)

        Unless 'rgrep' does something completely different from 'egrep', 'fgrep' or 'grep', you're wrong:
        $ cat foo $foo ->[2]; print $_->{bar}; $sum += $_->[0] for @array; $ fgrep -e '->' foo | perl -nwe '/(\S{3,80}->\S{5,80})/;print $1,"\n"' Use of uninitialized value $1 in print at -e line 1, <> line 1. Use of uninitialized value $1 in print at -e line 1, <> line 2. Use of uninitialized value $1 in print at -e line 1, <> line 3. $
        He does prefilter the line. But the filter is just for '->' while the pattern requires context around the '->'.
Re: Print all derefs and method calls in a directory (Friday golf)
by ikegami (Pope) on Jan 09, 2009 at 10:20 UTC

    Addressing the golfing request,

    # 123 rgrep -e'->' * | perl -ne '/(\S{3,80}->\S{5,80})/;print $1,"\n"' | pe +rl -pe's/^\(//' | perl -pe 's/^\+\+|^\-\-//' | sort | uniq

    is sufficiently equivalent to

    # 68 perl -ne's/^(\(|[+-]{2})//g,say for/(\S{3,80}->\S{5,80})/' *|sort -u

    And since you already assume that you can't have two dereferencing expressions on the same line,

    # 67 perl -ne's/^(\(|[+-]{2})//g,say for/\S{3,80}->\S{5,80}/g' *|sort -u
      Since you're using 'say', you have to use '-E' instead of '-e'.

      Note also that [+-]{2} is not equivalent to \+\+|-- as the former matches "-+" while the latter doesn't. Also, the original code will remove a leading "(--" from the line, while your code will not (it will either remove a leading '(' or a leading '--', '-+', '+-' or '--'). Finally, a /g modifier is useless if the pattern is anchored to the beginning of the string. And, if you're golfing, you shouldn't make a capture if you aren't using the result.

      Your s/// could be written as:

      s/^\(?([-+])\1//
      My entry (untested):
      perl -nE'/\(?([-+])\1.*?(\S{3,80}->\S{5,80})/&&say$2' *|sort -u
      I do think the 80 is a bit arbitrary, and
      perl -nE'/\(?([-+])\1.*?(\S{3,}->\S{5,})/&&say$2' *|sort -u
      is not only shorter, but likely to be preferred.

        Since you're using 'say', you have to use '-E' instead of '-e'.

        Oops!

        it will either remove a leading '(' or a leading '--', '-+', '+-' or '--')

        Oops!

        [+-]{2} is not equivalent to \+\+|--

        Indeed, but I deemed it acceptable.

        if you're golfing, you shouldn't make a capture if you aren't using the result.

        Not until Perl6. /...(?:...|...)/ is longer than /...(...|...)/. (Multiplying out the leading subexpression would have been shorter, but that's not the issue you raised.)

        I take your 69 and give you 51:

        perl -nE'/[-+(]*(\S{3,}->\S{5,})/&&say$1' *|sort -u
Re: Print all derefs and method calls in a directory (Friday golf)
by dragonchild (Archbishop) on Jan 09, 2009 at 18:40 UTC
    This is a job for PPI or -MO=Deparse.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2015-07-30 11:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (271 votes), past polls