Perl Introspection - A Perl Tutor Written in Perl

Reading a book to learn Perl is boring. How about read and run a Perl script to learn Perl? Here is my first version of a Perl script that produces a simple Perl Tutor.

How it works:

The Perl script scan.pl scans text format of this book and extracts the Perl statements plus comments (normally headline and immediate proceeding text ending with ":" of any Perl statement. To improve the script's output, I'm working on a new set of regular expressions and conditions to select comments that are directly related to the statements.)

Once Perl statements are extracted, they are duplicated. One set of the statements is quoted inside print statement for Perl to print out; the second set of statements is executed to produce output. These statements generate a running version of Perl script. Users just view/run this script to learn Perl's syntax and see the execution of each sample code...

Sample code generated by scan.pl:

#Special Array Indices
print "\n\n#3.Special Array Indices\n";
$rocks[0] = 'bedrock'; # One element...
$rocks[1] = 'slate'; # another...
$rocks[2] = 'lava'; # and another...
$rocks[3] = 'crushed rock'; # and another...
$rocks[99] = 'schist'; # now there are 95 undef elements
print "\$rocks[0] = 'bedrock'; # One element...\n";
print "\$rocks[1] = 'slate'; # another...\n";
print "\$rocks[2] = 'lava'; # and another...\n";
print "\$rocks[3] = 'crushed rock'; # and another...\n";
print "\$rocks[99] = 'schist'\n";
$end = $#rocks; # 99, which is the last element's index
print "\$end = \$#rocks; # 99, which is the last element's index : \n";
print "\$end = $end \n";
print "\$rocks[ \$end ]'s value : $rocks[ $end ] \n";

$number_of_rocks = $end + 1; # okay, but you'll see a better way later
$rocks[ $#rocks ] = 'hard rock'; # the last rock
print "\$number_of_rocks = \$end + 1; # okay, but you'll see a better way later\n";
print "\$number_of_rocks = $number_of_rocks \n";
print "\$rocks[ \$#rocks ] = 'hard rock'; # the last rock\n";
$rocks[ -1 ] = 'hard rock'; # easier way to do that last example
$dead_rock = $rocks[-100]; # gets 'bedrock'






This is a test run of the script against Chapter 3 - Lists and Arrays.

[shan@localhost perl]$./scan.pl chapter03.txt 3.pl

[shan@localhost perl]$./perl 3.pl


Perl Introspection written by a Perl script.

***** Chapter 3 - Lists and Arrays *****


#1. Accessing Elements of an Array
$fred[0] = "yabba";
$fred[1] = "dabba";
$fred[2] = "doo";
$fred[0]'s value: yabba


#2. The "." operation
$fred[1] .= "whatsis";
$number = 2.71828
$fred[$number - 1] # Same as printing $fred[1]
$fred[$number - 1]'s value: dabbawhatsis




#3.Special Array Indices
$rocks[0] = 'bedrock'; # One element...
$rocks[1] = 'slate'; # another...
$rocks[2] = 'lava'; # and another...
$rocks[3] = 'crushed rock'; # and another...
$rocks[99] = 'schist'
$end = $#rocks; # 99, which is the last element's index :
$end = 99
$rocks[ $end ]'s value : schist
$number_of_rocks = $end + 1; # okay, but you'll see a better way later
$number_of_rocks = 100
$rocks[ $#rocks ] = 'hard rock'; # the last rock
$rocks[ -200 ] = 'crystal'; # Will create fatal error!


@rocks : bedrock slate lava crushed rock


#4.List Literals

An array is a list of comma-separated values enclosed in parenthese.
These values form the elements of the list.

(1, 2, 3) # list of three values 1, 2, and 3
(1, 2, 3,) # the same three values (the trailing comma is ignored)
("fred", 4.5) # two values, "fred" and 4.5
( ) # empty list - zero elements
(1..100) # list of 100 integers
(1..5) # same as (1, 2, 3, 4, 5)
(1.7..5.7) # same thing - both values are truncated
(5..1) # empty list - .. only counts "uphill"
(0, 2..6, 10, 12) # same as (0, 2, 3, 4, 5, 6, 10, 12)
($m..$n) # range determined by current values of $m and $n
(0..$#rocks) # the indices of the rocks array from the previous section

#The qw Shortcut

("fred", "barney", "betty", "wilma", "dino")
qw( fred barney betty wilma dino ) # same as above, but less typing
qw! fred barney betty wilma dino !
qw/ fred barney betty wilma dino /
qw# fred barney betty wilma dino # # like in a comment!
qw( fred barney betty wilma dino )
qw{ fred barney betty wilma dino }
qw[ fred barney betty wilma dino ]
qw<>

#It can be useful if you were to need a list of Unix filenames:
qw{
/usr/dict/words
/home/rootbeer/.ispell_english
}


#5.List Assignment

($fred, $barney, $dino) = ("flintstone", "rubble", undef);
($fred, $barney) = ($barney, $fred); # swap those values
($betty[0], $betty[1]) = ($betty[1], $betty[0]);
($fred, $barney) = qw<>; # two ignored items
($wilma, $dino) = qw[flintstone]; # $dino gets undef
($rocks[0], $rocks[1], $rocks[2], $rocks[3]) = qw/talc mica feldspar quartz/;
@rocks = qw/ bedrock slate lava /;
@tiny = ( ); # the empty list
@giant = 1..1e5; # a list with 100,000 elements
@stuff = (@giant, undef, @giant); # a list with 200,001 elements
$dino = "granite";
@quarry = (@rocks, "crushed rock", @tiny, $dino);
@copy = @quarry; # copy a list from one array to another


#6.The pop and push Operators

The pop operator takes the last element off of an array and returns it:
@array = 5..9;
$fred = pop(@array); # $fred gets 9, @array now has (5, 6, 7, 8)
$barney = pop @array; # $barney gets 8, @array now has (5, 6, 7)
pop @array; # @array now has (5, 6). (The 7 is discarded.)

**Perl General Rule 1: as long as you dont change the meaning by removing the parentheses,

push(@array, 0); # @array now has (5, 6, 0)
push @array, 8; # @array now has (5, 6, 0, 8)
push @array, 1..10; # @array now has those ten new elements
@others = qw/ 9 0 2 1 0 /;
push @array, @others; # @array now has those five new elements (19 total)


#7. The shift and unshift Operators

@array = qw# dino fred barney #;
$m = shift(@array); # $m gets "dino", @array now has ("fred", "barney")
$n = shift @array; # $n gets "fred", @array now has ("barney")
shift @array; # @array is now empty
$o = shift @array; # $o gets undef, @array is still empty
unshift(@array, 5); # @array now has the one-element list (5)
unshift @array, 4; # @array now has (4, 5)
@others = 1..3;
unshift @array, @others; # @array now has (1, 2, 3, 4, 5)


#8. Interpolating Arrays into Strings

Like scalars, array values may be interpolated into a double-quoted string. Elements of
an array are automatically separated by spaces* upon interpolation:

@rocks = qw{ flintstone slate rubble };
print "quartz @rocks limestone";# prints five rocks separated by spaces
print "quartz @rocks limestone" --> quartz flintstone slate rubble limestone

@fred = qw(hello dolly);
$y = 2;
$x = "This is $fred[1]'s place"; # "This is dolly's place"
$x = "This is $fred[$y.1]'s place"; # same thing

@fred = qw(hello dolly);
$y = 2;
$x = "This is $fred[1]'s place"; # "This is dolly's place"
$x = "This is $fred[$y.1]'s place"; # same thing


#9. The foreach Control Structure

The foreach loop steps through a list of values, executing one iteration
(time through the loop) for each value:
foreach $rock (qw/ bedrock slate lava /) {
print "One rock is $rock.\n;"; # Prints names of three rocks
}
@rocks = qw/ bedrock slate lava /;
foreach $rock (@rocks) {
$rock = " $rock"; # put a tab in front of each element of @rocks
$rock .= "
"; # put a newline on the end of each
}
The rocks are:
flintstoneslaterubbleThe rocks are:
bedrock
slate
lava


#10. Perl's Favorite Default: $_
If you omit the control variable from the beginning of the foreach loop,
Perl uses its favorite default variable, $_.

foreach (1..10) { # Uses $_ by default
print "I can count to $_!\n";
}

$_ = "Yabba dabba doo\n";
print; # prints $_ by default ---> Yabba dabba doo