Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

print_r

by GhodMode (Pilgrim)
on Sep 25, 2007 at 06:11 UTC ( #640865=snippet: print w/replies, xml ) Need Help??
Description: Does Perl have something similar to print_r? The question has been asked before by people at all levels of expertise with Perl and PHP. The answer has often been Data::Dumper, but that is both more powerful and more complex than needed. This code will produce basically the same results as the popular PHP print_r without any settings or objects to worry about...
use strict;
use warnings;

my @array1 = qw( four five six );
my @array = qw( one two three );
push( @array, \@array1 );

my $string = "four";
my %hash   = (
    'first' => 'one',
    'second' => 'two',
    'third'  => 'three',
    'fourth' => \@array,
);

#print_r( @array );

print_r( \%hash );

sub print_r {
    package print_r;
    our $level;
    our @level_index;
    if ( ! defined $level ) { $level = 0 };
    if ( ! defined @level_index ) { $level_index[$level] = 0 };

    for ( @_ ) {
        my $element = $_;
        my $index   = $level_index[$level];

        print "\t" x $level . "[$index] => ";

        if ( ref($element) eq 'ARRAY' ) {
            my $array = $_;

            $level_index[++$level] = 0;

            print "(Array)\n";

            for ( @$array ) {
                main::print_r( $_ );
            }
            --$level if ( $level > 0 );
        } elsif ( ref($element) eq 'HASH' ) {
            my $hash = $_;

            print "(Hash)\n";

            ++$level;

            for ( keys %$hash ) {
                $level_index[$level] = $_;
                main::print_r( $$hash{$_} );
            }
        } else {
            print "$element\n";
        }

        $level_index[$level]++;
    }
} # End print_r
Replies are listed 'Best First'.
Re: print_r
by grinder (Bishop) on Sep 25, 2007 at 10:31 UTC

    Careful: this code doesn't deal with circular structures:

    my $r1 = [ 1 ]; my $r2 = [ 2, $r1 ]; push @$r1, $r2; print_r($r1);

    This will recurse endlessly until the heat death of the universe or you run out of swap, whichever comes first. Then again, perhaps the PHP implementation does as well.

    Minor issue: you don't want to explicitly state the package (main::print_r) when you call the function within itself. Using the unqualified name will allow it to work regardless of which package defines the routine.

    • another intruder with the mooring in the heart of the Perl

      grinder:  This will recurse endlessly until the heat death of the universe or you run out of swap, whichever comes first. Then again, perhaps the PHP implementation does as well.

      PHP's print_r (522) does indeed detect recursion after the first loop:
      <?php $r1 = array( 1 ); $r2 = array( 2, &$r1 ); array_push( $r1, &$r2 ); print_r($r1); ?>

      This will result in the following output:
      ( [0] => 1 [1] => Array ( [0] => 2 [1] => Array ( [0] => 1 [1] => Array *RECURSION* ) ) )

      Regards

      mwa
        recursion check:
        sub print_r { my $level=""; my @level_index=(); my @print_r_Recursion=(); print_rec (@_); undef @level_index; undef @print_r_Recursion; undef $level; sub print_rec { if ( ! defined $level ) { $level = 0 }; if ( ! defined @level_index ) { $level_index[$level] = 0 }; for ( @_ ) { my $element = $_; my $index = $level_index[$level]; if (ref($element) eq 'ARRAY' || ref($element) eq 'HASH'){ my $loop=0; for (@print_r_Recursion){ if (($element."") eq ($_."")){ $loop=1; last; } } if ($loop==1){ print "\t" x $level . "[$index] =&gt; ". ref($elem +ent) ." *recursion*\n"; next; } push @print_r_Recursion,$element; } print "\t" x $level . "[$index] =&gt; "; if ( ref($element) eq 'ARRAY' ) { my $array = $_; $level_index[++$level] = 0; print "(Array)\n"; for ( @$array ) { print_rec( $_ ); } --$level if ( $level &gt; 0 ); } elsif ( ref($element) eq 'HASH' ) { my $hash = $_; print "(Hash)\n"; ++$level; for ( keys %$hash ) { $level_index[$level] = $_; print_rec( $$hash{$_} ); } } else { print "$element\n"; } $level_index[$level]++; } } }
      This will recurse endlessly until the heat death of the universe or you run out of swap, whichever comes first. Then again, perhaps the PHP implementation does as well.
      You're right: +1 :) I don't know how PHP's print_r handles this either. I guess a solution to this problem would be to add an arbitrary limit to the $level variable and have it stop calling print_r when it gets to the limit. I have to ask, though, why would you have an array that references itself?
      Minor issue: you don't want to explicitly state the package (main::print_r) when you call the function within itself. Using the unqualified name will allow it to work regardless of which package defines the routine.
      I did this initially, but I got the following error:
      Undefined subroutine &print_r::print_r called at ./print_r.pl line 55.
      To make it easy to use in other programs, I gave it's own package so that there would be no chance of another global variable with the same name in the main namespace, but I still wanted print_r to be in in the main namespace. I guess it was just a warning, but this was the only way I could get it to work without errors.
      --
      -- Ghodmode
      
      Blessed is he who has found his work; let him ask no other blessedness.
      -- Thomas Carlyle
        I did this initially, but I got the following error: Undefined subroutine &print_r::print_r called at ./print_r.pl line 55.

        Odd. If I take out the main:: prefix, and the package declaration I receive no error. In fact, I've never seen a package declaration within a subroutine. It seems strange, to say the least, and I wonder if it does what you think it does. What do you think it does?

        Looking more closely at the code, I suspect you want my variables and not our.

        As to why you want to have an object reference itself, one answer is "it makes life easier". It most frequently occurs in hierarchical structures, where one of the keys at a node will be a reference to an ancestor or sibling. It makes it easier to move around in the object without having to maintain context. Have a look at an XML::Twig object some time.

        • another intruder with the mooring in the heart of the Perl

Re: print_r
by virtualsue (Vicar) on Sep 25, 2007 at 08:53 UTC
    I don't use PHP, and I'm probably not the only one. Could you please add a brief description of what 'print_r' does?
      virtualsue I don't use PHP, and I'm probably not the only one. Could you please add a brief description of what 'print_r' does?

      It prints out data items and references, it traces complex data structures down to the last item (arrays, hashes), example (PHP, so be warned!):

      <?php $record = array( 'convict' => array( 'name' => 'virtualsue', 'link' => 'www.perlmonks.org/?node_id +=70099'), 'penalty' => array( 'type' => '48h TV w/out breaks', 'warden'=> 'Mike Judge') ); print_r($record); ?>

      The last line produces exactly the following output:
      Array ( [convict] => Array ( [name] => virtualsue [link] => www.perlmonks.org/?node_id=70099 ) [penalty] => Array ( [type] => 48h TV w/out breaks [warden] => Mike Judge ) )
      Regards mwa
      Well, if you don't use PHP, then this probably wouldn't appeal to you anyway :) However, I linked to the print_r function documentation on php.net in the original post for this reason.
      --
      -- Ghodmode
      
      Blessed is he who has found his work; let him ask no other blessedness.
      -- Thomas Carlyle
Re: print_r
by f00li5h (Chaplain) on Mar 30, 2009 at 03:28 UTC

    Not that I'd ever use php, but if I had done it for, say, 6 or 7 years, I'd suggest that print_r is the least useful of php's dump-data-struct methods... and that var_export is far more useful...

    ... perl for var_export is Data::Dumper::Dumper

    @_=qw; ask f00li5h to appear and remain for a moment of pretend better than a lifetime;;s;;@_[map hex,split'',B204316D8C2A4516DE];;y/05/os/&print;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://640865]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2018-07-18 04:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (383 votes). Check out past polls.

    Notices?