When I write Perl, on my own, it looks like the following. This is Perl written in the “functional” style I advocate.
The code takes a listing of simple definitions:
tree
noun
something organic with leaves
_etc._
and turns it into LaTeX Beamer–class slide markup.
\frame{
\frametitle{tree }
\begin{itemize}
\item tree
\pause
\item noun
\pause
\item
something organic with leaves
\end{itemize}
}
When the Beamer LaTeX code is complied with pdflatex it produces a slide show that winds up looking something like…
You can see how something like this is handy for someone studying their GRE Vocabulary builder. Code after the jump.
[code lang=”perl”]
!/usr/bin/perl
use warnings; use strict; use Data::Dumper; use vars qw/$end_of_document $word $part $meaning/;
=head1 NAME
wordlst_to_beamer.pl - A plaintext to LaTeX-Beamer dialect converter
=head1 SYNOPSIS
wordlst_to_beamer definition_file
=head1 DESCRIPTION
This program takes a simply formatted text file that contains a series of ”
blocks”. Each block is equivalent to one definition ( see SOURCE DEFINITION ).
Each definition is then taken to be a “slide” in LaTeX Beamer style.
The purpose of doing so is to make each slide, effectively, a flash card.
The word is printed, pause, part of speech given, pause, and then the
definition given.
=head1 SOURCE DEFINITION
The text file that is given as an argument to the program should be a collection of definitions separated by a double carriage return.
tree noun a living thing with leaves
happy adjective a feeling like you want to dance Charleston
I
=head1 SUBROUTINES
Given the beautiful functional style in which this code was written and the relative brevity of each routine, the code serves as sufficient documentation.
=cut
&main();
#
Subroutines
#
sub main { &report_status( &produce_beamer_body( &test_contents_integrity ( &load_contents_of_file( &test_validity_of_file ( &get_file_to_operate_on( &load_environment() )))))); }
#
sub report_status { unless ( $_[0] ) { print “Successfully ran.\n” } else { die “Error!\n” } }
#
sub produce_beamer_body { (my $latex_output_file = $_[0]->{file} ) =~ s/..*$// ;
open (LATEX, ">$latex_output_file.tex");
# A technique to tell Perl not to paginate
# ( i.e. re-print LATEX_TOP format ) again
my $ltx = select LATEX;
$= = 9990;
select $ltx;
my ($ds) = $_[0]->{data_structure};
my @order = sort { $a <=> $b } ( keys ( %$ds ) );
for ( @order )
{
$word = $ds->{$_}[0];
$part = $ds->{$_}[1];
$meaning = $ds->{$_}[2];
chomp($word, $part, $meaning);
write (LATEX);
}
print LATEX $end_of_document;
close LATEX;
return $? }
#
sub test_contents_integrity { my $content_string = join (”, @{+ $_[0]->{contents} } ); my @clustered_contents_ray = split ( /\n\n/, $content_string);
my $counter = 0;
my $cell_counter = 0;
my %data_structure;
for ( @clustered_contents_ray )
{
$counter++;
my @temp_array = split ( /\n/, $_);
if ( scalar ( @temp_array ) != 3 )
{
print "There was something amiss with entry:\n$_";
exit 1;
}
else
{
$cell_counter +=3;
}
$data_structure{$counter} = \@temp_array;
}
if ( ($cell_counter % 3) == 0 ) { $[0]->{‘data_structure’} = \%data_structure; return $[0]; } else { die “Data structure was anomalous.” } }
#
sub load_contents_of_file
{
my $f = $[0]->{file_fullpath};
open ( IN, $f ) or die (“Could not open $f because [$!]”);
my @contents =
#
sub test_validity_of_file { my $f = $[0]->{file_fullpath}; die (“Could not read file [$f][$!]”) unless ( -r $f ); return $[0]; }
#
sub get_file_to_operate_on { my $filename = shift( @ARGV ) || ”; my $default_filename=’hit_parade_list_1.txt’;
my $payload = {};
if ( $filename =~ /\w/)
{
chomp $filename;
$payload->{file} = $filename
}
else
{
$payload->{file} = $default_filename
}
$payload->{file_fullpath} =
join ( "/", (`pwd` =~ /(.*)\n/),
$filename ? $filename : $default_filename);
return $payload;
}
#
sub load_environment {
format LATEX_TOP= \documentclass{beamer} \begin{document} .
format LATEX = \frame{ \frametitle{@<<<<<<<<<<<<<<} $word \begin{itemize} \item @<<<<<<<<<<<<<<< $word \pause \item @<<<<<<<<<<<< $part \pause \item @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $meaning \end{itemize} } .
$end_of_document = < \end{document}; EOF
; } [/code]
August 15th, 2008 at 11:26 pm
[…] an earlier post I provided code demonstrating my “functional” Perl idiom. The purpose of that code was to take a very simply formatted text file and to turn it into LaTeX […]
August 16th, 2008 at 6:33 am
Calling functions like this:
&function();
is a Perl4 leftover and deprecated in Perl5.
August 16th, 2008 at 3:22 pm
Zeek: You’re absolutely correct. You may derive from this that I have been migrating / editing a lot of Perl 5.00 code where the previous authors’ history hadn’t quite worn out. A simple perl -pe command has fixed my code to your recommendation.
August 16th, 2008 at 5:36 pm
The formatting looks OK from far away, but the naming conventions, OMFG. I don’t know what to say.
Giving variables names like ‘data_structure’ and ‘temp_array’ is just wrong. And what is a ‘ray’ in the context of your program? @clustered_contents_ray ??
And using the special variables to refer to input, without ever naming them, is bad practice. I’m talking about your use of things like $[0]->{contents}, where $[0] is never given a name.
Also it’s considered bad practice to use $_ as much as you are. Name your variables.
Also perl5 has some new idioms you should take advantage of. Instead of:
if ( scalar ( @temp_array ) != 3 )
{
print “There was something amiss with entry:n$_”;
exit 1;
}
}
else
You can say:
die “There was something amiss with entry:n$_nn”
unless (@temp_array == 3);
Still very clear. No ‘else’ needed either, if your program is exiting. And give $_ a name.
August 16th, 2008 at 5:42 pm
Not surprisingly, the comment formatting was messed up on my post. When reading, insert indentation, backslashes and the occasional other missing character (underscore after dollar sign, in some places) where necessary.
August 16th, 2008 at 11:23 pm
Wow, I’m really surprised this post is generating this much commentary. You never know what’s going to attract people.
My key focus in this post was to underscore how much I like to run main() as a “stack” of functions. The independent sub-strata of the code were not my key focuses.
I’ll agree that the “consequent first” if statement is preferable ( I think I had something there in the else condition originally ). You don’t see it in this code, but I use it, a lot.
But I certainly don’t think using $_ is as abhorrent as you make it out to be. If a reader understands the Perl iterators and knows that $_ is automatically set, why not take advantage? Your opinion that this is “not best practice” is in opposition to Joseph Hall’s Effective Perl Programming which encourages the practice.
As far as naming convention goes, they’re a bit wordy and admittedly a bit uninformative, but given the very limited scope of this post their naming wasn’t a huge focus ( there’s only one array with the very primitive source data ) there’s only one HoA, etc.