Question

use strict;

sub main {
    print shift;
    nested(@_);
}

sub nested {
    print shift;
    deep(@_);
}

sub deep {
    print shift;
}

my @list = qw(main nested deep);
main(@list);

How to get this "stair-step" output:

>main
>>nested
>>>deep

Note functions main, nested and deep - required and may be call over and over in different variations

Was it helpful?

Solution

I'd generally pass around an indentation string, along these lines:

use strict;

sub main {
    my ($strings, $indent) = @_;
    $indent = "" unless defined $indent;
    print $indent, shift(@$strings), "\n";
    nested($strings, $indent."\t");
}

sub nested {
    my ($strings, $indent) = @_;
    $indent = "" unless defined $indent;
    print $indent, shift(@$strings), "\n";
    deep($strings, $indent."\t");
}

sub deep {
    my ($strings, $indent) = @_;
    $indent = "" unless defined $indent;
    print $indent, shift(@$strings), "\n";
}

my @list = qw(main nested deep);
main(\@list);

A similar technique is to pass around an indent level as an integer, incrementing it as needed:

use strict;

sub main {
    my ($strings, $indent) = @_;
    $indent = 0 unless defined $indent;
    print "\t" x $indent, shift(@$strings), "\n";
    nested($strings, $indent+1);
}

sub nested {
    my ($strings, $indent) = @_;
    $indent = 0 unless defined $indent;
    print "\t" x $indent, shift(@$strings), "\n";
    deep($strings, $indent+1);
}

sub deep {
    my ($strings, $indent) = @_;
    $indent = 0 unless defined $indent;
    print "\t" x $indent, shift(@$strings), "\n";
}

my @list = qw(main nested deep);
main(\@list);

OTHER TIPS

It looks like your array is a list of subroutine names that you want to be called in order. To do that you need to disable strict 'refs' temporarily. This example demonstrates.

Note that the code for all three subroutines is identical. Presumably you will want to put something between the print trace output and the call to the next subroutine in the list the differentiates the three blocks of code.

I have written it so that the number of preceding angle brackets is passed as the second parameter to the subroutines, and defaults to 1 if no value was passed (for the initial call of the sequence).

use strict;
use warnings;

my @list = qw(main nested main deep nested);
main(\@list);

sub main {
  my ($list, $indent) = (@_, 1);
  my $name = shift @$list;
  print '>' x $indent, $name, "\n";

  no strict 'refs';
  &{$list->[0]}($list, $indent + 1) if @$list;
}

sub nested {
  my ($list, $indent) = (@_, 1);
  my $name = shift @$list;
  print '>' x $indent, $name, "\n";

  no strict 'refs';
  &{$list->[0]}($list, $indent + 1) if @$list;
}

sub deep {
  my ($list, $indent) = (@_, 1);
  my $name = shift @$list;
  print '>' x $indent, $name, "\n";

  no strict 'refs';
  &{$list->[0]}($list, $indent + 1) if @$list;
}

output

>main
>>nested
>>>main
>>>>deep
>>>>>nested

Here's a way to maintain the indent level in it's own state:

sub decorator {

    my $string = +shift;
    my $level = 0;

    return sub { $string x ++$level }
}

my $steps = decorator( '>' );  # Each time $steps->() is called
                               # the indent level increases

print $steps->(), $_, "\n" for qw( main deep nested );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top