[11477] in Perl-Users-Digest
Perl-Users Digest, Issue: 5077 Volume: 8
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Sat Mar 6 20:07:24 1999
Date: Sat, 6 Mar 99 17:01:26 -0800
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Sat, 6 Mar 1999 Volume: 8 Number: 5077
Today's topics:
SRC: perlpoint demo <tchrist@mox.perl.com>
Sub calls: how can I do this? <rafala@loyolanet.campus.mci.net>
Upload file without CGI.pm - possible? ("Adrian Fiorinni")
Re: Upload file without CGI.pm - possible? <gellyfish@btinternet.com>
Special: Digest Administrivia (Last modified: 12 Dec 98 (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: 6 Mar 1999 10:24:09 -0700
From: Tom Christiansen <tchrist@mox.perl.com>
Subject: SRC: perlpoint demo
Message-Id: <7bsf0t$96g$1@nntp.Stanford.EDU>
At Linux World this past week where I gave a presentation on Perl,
I was aghast to see all these so-called Unix advocates using Microsoft
for their presentations. This was particularly embarrassing given the
titles of some of their talks. And these people calimed to be programmers.
People couldn't understand how I was actually using a Unix system to
show my slides with, so here's the system I use. It starts with
files in "slidepod" format, like this:
=Everyone Has an Opinion
* Style can easily become a religious issue.
* What I am about to tell you is mostly my opinion. It includes
both general philosophy and concrete tips.
* Warning: I may not always follow my own tips. :-)
* I do not expect all of you to agree with me all the time. Choose a
style and stick with it. Consistency is critical.
=Program Perl, Not C/BASIC/Java/Pascal/etc
* `Just because you I<can> do something a particular way doesn't
mean you I<should> do it that way.' --I<Programming Perl>
* If you find yourself writing code that looks like C code, or
BASIC, or Java, or Pascal, you are probably short-changing yourself.
You need to learn to program idiomatic Perl -- which does not mean
obfuscatory Perl. It means Perl in its own idiom: native Perl.
* Fall not into the folly of avoiding certain Perl idioms for fear
that someone who maintains your Perl code won't understand it because
they don't know Perl. This is ridiculous! That person shouldn't
be maintaining a language they don't understand. You don't write
your English so that someone who only speaks French or German can
understand you, or use Latin letters when writing Greek.
=Elegance
* `It is very hard to get things both right (coherent and correct)
and usable (consistent enough, attractive enough).' --Dennis Ritchie
* Think first. Then hack. Now throw it out. Repeat.
What this package does is convert files in that format into troff, html,
and postscript forms using pp2roff and pp2html (included).
This is something of a "rigged demo", in that all kinds of things are
hardwired, from the Makefile to some of the title strings. Feel free to
hack and use. The original troff slide macros were done by Rob Kolstad.
I've used them for at least a decade. Try them. If you make it better,
please send me mail with updates.
--tom
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1999-03-06 10:01 MST by <tchrist@jhereg.perl.com>.
# Source directory was `/home/tchrist'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
# This format requires very little intelligence at unshar time.
# "if test", "echo", "mkdir", and "sed" may be needed.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 3085 -rw-r--r-- perlpoint/pp2html
# 530 -rwxr-xr-x perlpoint/pp2roff
# 24997 -rw-r--r-- perlpoint/Style.pp
# 1784 -rw-r--r-- perlpoint/Intro.pp
# 5618 -rw-r--r-- perlpoint/slidemacs
# 91 -rwxr-xr-x perlpoint/ppages
# 605 -rw-r--r-- perlpoint/Makefile
# 315 -rw-r--r-- perlpoint/title.nr
#
echo=echo
if mkdir _sh20212; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= perlpoint/pp2html ==============
if test ! -d 'perlpoint'; then
$echo 'x -' 'creating directory' 'perlpoint'
mkdir 'perlpoint'
fi
if test -f 'perlpoint/pp2html' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'perlpoint/pp2html' '(file already exists)'
else
$echo 'x -' extracting 'perlpoint/pp2html' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'perlpoint/pp2html' &&
X#!/usr/bin/perl -w
X
Xuse Getopt::Long;
X
X$links = 1;
X
XGetOptions(
X "class=s" => \$course,
X "section=s" => \$section,
X "links!" => \$links,
X) or die <<EOUSAGE;
Xusage: $0 [--class COURSE] [--section WHICH]
XEOUSAGE
X
Xopen(IDX, "> index.html") || die "can't open index.html: $!";
Xprint IDX <<EOF;
X<HTML>
X<HEAD>
X<TITLE>$course: $section</TITLE>
X</HEAD>
X<BODY BGCOLOR="#000000" TEXT="#FFFFFF" LINK="#FFFF00" ALINK="#0000FF" VLINK="#808080">
X<H1 ALIGN=CENTER>$section</H1>
X<OL>
XEOF
X
Xmy $cur = 0;
X
X$/ = '';
X
Xsub escapes {
X s!&!save("&")!ge;
X s!<!save("<")!ge;
X s!>!save(">")!ge;
X s!"!save(""")!ge;
X}
X
Xsub save {
X my $it = $_[0];
X $it =~ y/\000-\177/\200-\377/;
X return $it;
X}
X
Xwhile (<>) {
X chomp;
X
X if (/^\s/) {
X escapes();
X y/\200-\377/\000-\177/;
X s/\n+\Z//;
X print "<TABLE BGCOLOR=\"#0000FF\" CELLSPACING=0 CELLPADDING=0 BORDER=0><TR><TD><PRE><FONT COLOR=\"#FFFFFF\">\n";
X print;
X print "</FONT></PRE></TD><TD> </TD><TD> </TD></TR></TABLE>\n";
X next;
X }
X
X s{I<(.*?)>}{save("<I>$1</I>")}gesx;
X s{C<(.*?)>}{save("<CODE>$1</CODE>")}gesx;
X s{B<(.*?)>}{save("<B>$1</B>")}gesx;
X s/E<lt>/</g; s/E<gt>/>/g;
X
X if (/^=\s*(.*)/) {
X my $title = $1;
X $title =~ y/\200-\377/\000-\177/;
X $cur++;
X $slide[$cur] = $title;
X print IDX qq(<LI><A HREF="slide$cur.html">$title</A>\n);
X
X if ($cur > 1) {
X print "</UL>\n";
X if ($links) {
X print qq(<HR>);
X print qq(<TABLE WIDTH=\"100%\"><TR><TD><FONT SIZE=-2>);
X print qq(Forward to <A HREF="slide$cur.html">$slide[$cur]</A>\n);
X if ($cur > 2) {
X $prev = $cur - 2;
X print qq(<BR>Back to <A HREF="slide$prev.html">$slide[$cur - 2]</A>\n);
X }
X print qq(<BR>Up to $section section <A HREF="index.html">index</A>\n);
X print qq(<BR>Up to $course course <A HREF="../index.html">index</A>\n);
X print qq(</FONT></TD>);
X }
X done();
X }
X
X open(SLIDE, "> slide$cur.html")
X || die "can't open slide$cur.html: $!";
X select SLIDE;
X
X print <<EOF;
X<HTML>
X<HEAD>
X<TITLE>$course, $section $cur: $title</TITLE>
X</HEAD>
X<BODY BGCOLOR="#000000" TEXT="#FFFFFF" ALINK="#FF0000" VLINK="#8080FF" LINK="#2020FF">
X<CENTER>
X<H1>$title</H1>
X</CENTER>
X
X<UL>
XEOF
X next;
X
X }
X
X s!([\$\@%]\w+)!save("<CODE>$1</CODE>")!ge;
X escapes();
X s/^\*\s*(.*)/<LI>$1<P>/gms;
X y/\200-\377/\000-\177/;
X print;
X}
X
Xif ($cur > 1) {
X print "</UL>\n";
X if ($links) {
X print qq(<HR><TABLE WIDTH=\"100%\"><TR><TD><FONT SIZE=-2>);
X if ($cur > 2) {
X $prev = $cur - 2;
X print qq(Back to <A HREF="slide$prev.html">$slide[$cur - 2]</A>\n);
X }
X print qq(<BR>Up to $section section <A HREF="index.html">index</A>\n);
X print qq(</FONT></TD>);
X }
X done();
X}
X
Xprint IDX <<"EOF";
X</OL>
X</BODY>
X</HTML>
XEOF
X
Xsub done {
X $this = $cur - 1;
X
Xprint <<EOF;
X<TD ALIGN=RIGHT><FONT SIZE=-1>
X<I>$course: $section - $this</I><P>
X<SMALL>
XCopyright © 1998, Tom Christiansen
X<BR>
XAll rights reserved.
X</SMALL>
X</FONT></TD></TR></TABLE>
X<HR>
X</BODY>
X</HTML>
XEOF
X}
X
X
SHAR_EOF
: || $echo 'restore of' 'perlpoint/pp2html' 'failed'
fi
# ============= perlpoint/pp2roff ==============
if test -f 'perlpoint/pp2roff' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'perlpoint/pp2roff' '(file already exists)'
else
$echo 'x -' extracting 'perlpoint/pp2roff' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'perlpoint/pp2roff' &&
X#!/usr/bin/perl
X
X$/ = '';
X
X$TOP = <<EOF;
X.\\"-----------------------------------------------------------
X.bp
X.au "TSC \\- perl.xx"
X
X.c
XEOF
X
Xwhile (<>) {
X chomp;
X s/\\/\\e/g;
X s{^=(.*)}{$TOP$1\n};
X if (/^\*\s*/) {
X s/^ (?=\S)//gm;
X s{^\*\s*}{.2\n}gm;
X }
X
X if (/^[\t ].*\S/s) {
X s/^ //gm;
X print <<EO_DISPLAY;
X.b
X.sz -7
X.sp .5
X$_
X.sp .5
X.sz +7
X.e
XEO_DISPLAY
X } else {
X s{I<(.*?)>}{\\f(BI$1\\fP}g;
X s{C<(.*?)>}{\\f(CB$1\\fP}g;
X s{B<(.*?)>}{\\f(BI$1\\fP}g;
X s/\s*--\s*/ \\(en /g;
X print $_, "\n";
X }
X}
SHAR_EOF
: || $echo 'restore of' 'perlpoint/pp2roff' 'failed'
fi
# ============= perlpoint/Style.pp ==============
if test -f 'perlpoint/Style.pp' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'perlpoint/Style.pp' '(file already exists)'
else
$echo 'x -' extracting 'perlpoint/Style.pp' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'perlpoint/Style.pp' &&
X=Everyone Has an Opinion
X
X* Style can easily become a religious issue.
X
X* What I am about to tell you is mostly my opinion. It
Xincludes both general philosophy and concrete tips.
X
X* Warning: I may not always follow my own tips. :-)
X
X* I do not expect all of you to agree with me all the time.
XChoose a style and stick with it. Consistency is critical.
X
X* I owe indirectly K&P, K&R, S&W, Rob Pike, and Larry Wall for laying
Xthe foundations, and directly Jon Orwant, Mark-Jason Dominus, and Nat
XTorkington for reviewing early versions of these notes.
X
X* `Under no circumstances should you program the way I say to because I
Xsay to; program the way you think expresses best what you're trying to
Xaccomplish in the program. And do so consistently and ruthlessly.'
X --Rob Pike
X
X=Program Perl, Not C/BASIC/Java/Pascal/etc
X
X* `Just because you I<can> do something a particular way doesn't mean
Xyou I<should> do it that way.' --I<Programming Perl>
X
X* If you find yourself writing code that looks like C code, or BASIC, or
XJava, or Pascal, you are probably short-changing yourself. You need to
Xlearn to program idiomatic Perl -- which does not mean obfuscatory Perl.
XIt means Perl in its own idiom: native Perl.
X
X* Fall not into the folly of avoiding certain Perl idioms for fear
Xthat someone who maintains your Perl code won't understand it because
Xthey don't know Perl. This is ridiculous! That person shouldn't be
Xmaintaining a language they don't understand. You don't write your
XEnglish so that someone who only speaks French or German can understand
Xyou, or use Latin letters when writing Greek.
X
X=Elegance
X
X* `It is very hard to get things both right (coherent and correct) and
Xusable (consistent enough, attractive enough).' --Dennis Ritchie
X
X* Strive always to create code that is functional, minimal, flexible,
Xand understandable -- not necessarily in that order.
X
X* Think first. Then hack. Now throw it out. Repeat.
XFred Brooks says, `Build one to throw away.'
XAlways rewrite your code from scratch, preferably B<twice>.
Xjust as did it with drafts of papers in grammar school. It
Ximproves understanding, gets the creative juices flowing, and
Xproduces a far finer end-product.
X
X* Sometimes making code shorter improves maintainability; other
Xtimes it does not.
X
X=Defensive Programming
X
X* use strict
X* #!/usr/bin/perl -w
X* Check B<all> syscall return values, printing $!
X* Watch for external program failures in $?
X* Check $@ after C<eval""> or C<s///ee>.
X* Parameter asserts
X* #!/usr/bin/perl -T
X* Always have an C<else> after a chain of C<elsif>s
X* Put commas at the end of lists to so your program won't break if someone
Xinserts another item at the end of the list.
X
X=The Art of Commenting Code
X
X* Explain what the code does, don't just perl2englishify.
X* Eschew gaudy block banners.
X* Use comments in regexes with C</x>.
X* Comment entire blocks, not single lines.
X* `Comments on data are usually much more helpful than on algorithms.'
X(Rob Pike)
X* `Basically, avoid comments. If your code needs a comment to be
Xunderstood, it would be better to rewrite it so it's easier to understand.'
X(Rob Pike)
X
X=On the Naming of Names (Form)
X
X* `I eschew embedded capital letters in names; to my prose-oriented
Xeyes, they are too awkward to read comfortably. They jangle like bad
Xtypography.' (Rob Pike)
X
X* `C<IEschewEmbeddedCapitalLettersInNames
XToMyProseOrientedEyes
XTheyAreTooAwkwardToReadComfortably
XTheyJangleLikeBadTypography>.'
X(TheAntiPike)
X
X* While short identifiers like $gotit are probably ok, use underscores to
Xseparate words. It is generally easier to read $var_names_like_this than
X$VarNamesLikeThis, especially for non-native speakers of English. It's
Xalso a simple rule that works consistently with VAR_NAMES_LIKE_THIS.
X
X* You may find it helpful to use letter case to indicate
Xthe scope or nature of a variable. For example:
X
X $ALL_CAPS_HERE constants only (beware clashes with perl vars!)
X $Some_Caps_Here package-wide global/static
X $no_caps_here function scope my() or local() variables
X
X* Function and method names seem to work best as all
Xlowercase. E.g., $obj->as_string().
X
X=On the Naming of Names (Content)
X
X* `Procedure names should reflect what they do; function names should
Xreflect what they return.' --Rob Pike.
X
X* Name objects so that they read well in English. For example, predicate
Xfunctions should usually be named with `is', `does', `can', or `has'.
XThus, C<&is_ready> is better than C<&ready> for the same function,
X
X* Therefore, C<&canonize> as a void function (procedure),
XC<&canonical_version> as a value-returning function, and C<&is_canonical> for
Xa boolean check.
X
X* The C<&abc2xyz> and C<&abc_to_xyz> forms are also well established
Xfor conversion functions or hash mappings.
X
X* Hashes usually express some I<property> of the keys, and are used with
Xthe English word `of' or the possessive form. Name hashes for their
Xvalues, not their keys.
X
X GOOD:
X %color = ('apple' => 'red', 'banana' => 'yellow');
X print $color{'apple'}; # Prints `red'
X
X BAD:
X %fruit = ('apple' => 'red', 'banana' => 'yellow');
X print $fruit{'apple'}; # Prints `red'
X
X=Length of Variable Names
X
X* `The appropriate length of a name is directly proportional to the size
Xof its scope.' --Mark-Jason Dominus
X
X* Length of identifiers is not a virtue; clarity is. Don't write this:
X
X for ($index = 0; $index < @$array_pointer; $index++) {
X $array_pointer->[$index] += 2;
X }
X
XWhen you should write:
X
X for ($i = 0; $i < @$ap; $i++) {
X $ap->[$i] += 2;
X }
X
X(One could argue for a better name than $ap, though. Or not.)
X
X* Global variables deserve longer names than local ones,
Xbecause their context is hard to see. For example,
X%State_Table is a program global, but $func might be
Xa local state pointer.
X
X foreach $func (values %State_Table) { ... }
X
X=Parallelism
X
X* Code legibility is dramatically increased by consistency
Xand parallelism. Compare
X
X my $filename = $args{PATHNAME};
X my @names = @{ $args{FIELDNAMES} };
X my $tab = $args{SEPARATOR};
X
Xwith
X
X my $filename = $args{PATHNAME};
X my @names = @{$args{FIELDNAMES}};
X my $tab = $args{SEPARATOR};
X
X* Line up your # comments or your C<|| die> all at one column:
X
X socket(SERVER, PF_UNIX, SOCK_STREAM, 0) || die "socket $sockname: $!";
X bind (SERVER, $uaddr) || die "bind $sockname: $!";
X listen(SERVER,SOMAXCONN) || die "listen $sockname: $!";
X
X=Embrace && and || for Control and Values
X
X* Perl's && and || operators short circuit like C's, but return
Xdifferent values: they return the first thing that resolves them.
X
X* This is most often used with ||:
X
X ++$count{ $shell || "/bin/sh" };
X
X $a = $b || 'DEFAULT';
X
X $x ||= 'DEFAULT';
X
X* Sometimes it can be done with && also, usually providing the
Xfalse value is '' not 0. (False tests in Perl return '' not 0!).
X
X $nulled_href = $href . ($add_nulls && "\0");
X
X=Learn Precedence
X
X* It is a myth that you can just plop in C<and> and C<or>
Xwherever you'd been using the punctuation versions. They
Xhave difference precedences. You B<must> learn precedence.
XAnd a few parens seldom hurt.
X
X print FH $data || die "Can't write to FH: $!"; # NO
X print FH $data or die "Can't write to FH: $!"; # YES
X
X $a = $b or $c; # bug: this is wrong
X ($a = $b) or $c; # really means this
X $a = $b || $c; # better written this way
X
X @info = stat($file) || die; # oops, scalar sense of stat!
X @info = stat($file) or die; # better, now @info gets its due
X
X* Careful with parens here:
X
X $a % 2 ? $a += 10 : $a += 2
X
XReally means this:
X
X (($a % 2) ? ($a += 10) : $a) += 2
X
XRather than this:
X
X ($a % 2) ? ($a += 10) : ($a += 2)
X
X=Don't Overdo `?:'
X
X* Using C<?:> for control flow may get you talked about. Better
Xto use an C<if/else>. And seldom if ever nest ?:.
X
X # BAD
X ($pid = fork) ? waitpid($pid, 0) : exec @ARGS;
X
X # GOOD:
X if ($pid = fork) {
X waitpid($pid, 0);
X } else {
X die "can't fork: $!" unless defined $pid;
X exec @ARGS;
X die "can't exec @ARGS: $!";
X }
X
X* Best as an expression:
X
X $State = (param() != 0) ? "Review" : "Initial";
X
X printf "%-25s %s\n", $Date{$url}
X ? (scalar localtime $Date{$url})
X : "<NONE SPECIFIED>",
X
X=Never define "TRUE" and "FALSE"
X
X* The language understands booleans. Never define them
Xyourself! This is terrible code:
X
X $TRUE = (1 == 1);
X $FALSE = (0 == 1);
X
X if ( ($var =~ /pattern/ == $TRUE ) { .... }
X if ( ($var =~ /pattern/ == $FALSE ) { .... }
X if ( ($var =~ /pattern/ eq $TRUE ) { .... }
X if ( ($var =~ /pattern/ eq $FALSE ) { .... }
X
X sub getone { return "This string is true" }
X
X if ( getone() == $TRUE ) { .... }
X if ( getone() == $FALSE ) { .... }
X if ( getone() eq $TRUE ) { .... }
X if ( getone() eq $FALSE ) { .... }
X
X* Imagine the silliness of this progression, and stop at the
Xfirst one.
X
X if ( getone() ) { .... }
X if ( getone() == $TRUE ) { .... }
X if ( (getone() == $TRUE) == $TRUE ) { .... }
X if ( ( (getone() == $TRUE) == $TRUE) == $TRUE ) { .... }
X
X=Embrace Pattern Matching
X
X* Regular Expressions are your friend. More than that, they're
Xa whole new way of thinking.
X
X* Just as chess players see patterns in the board positions their pieces
Xcontrol, Perl adepts look at data in terms of patterns.
X
X* Although most modern programming languages offer primitive pattern
Xmatching tools, usually through an extra library, Perl's patterns are
Xdirectly integrated into the language core. C</.../>, $1, etc.
X
X* Perl's patterns boast features not found in other languages' pattern
Xmatching, features that encourage a whole different way of looking
Xat data.
X
X=Changing I<en passant>
X
X* You can copy and change all at once:
X
X chomp($answer = <TTY>);
X
X ($a += $b) *= 2;
X
X # strip to basename
X ($progname = $0) =~ s!^.*/!!;
X
X # Make All Words Title-Cased
X ($capword = $word) =~ s/(\w+)/\u\L$1/g;
X
X # /usr/man/man3/foo.1 changes to /usr/man/cat3/foo.1
X ($catpage = $manpage) =~ s/man(?=\d)/cat/;
X
X @bindirs = qw( /usr/bin /bin /usr/local/bin );
X for (@libdirs = @bindirs) { s/bin/lib/ }
X print "@libdirs\n";
X | /usr/lib /lib /usr/local/lib
X
X=Negative Array Subscripts
X
X* To get the last element in a list or array, use C<$array[-1]> instead
Xof C<$array[$#array]>. The former works on both lists and arrays,
Xbut the latter does not.
X
X* Remember that C<substr>, C<index>, C<rindex>, and C<splice>
Xalso accept negative subscripts to count back from the end.
X
X split(@array, -2); # pop twice
X
X* Remember substr is lvaluable:
X
X substr($s, -10) =~ s/ /./g;
X
X=Embrace Hashes
X
X* Until you start thinking in terms of hashes, you're
Xnot thinking in Perl. They can often replace lengthy
Xloops or complex algorithms.
X
X* Use a hash whenever you want to represent a set, a relation,
Xa table, a structure, or a record.
X
X* The words `in', `unique', `first', and `duplicate' should
Xall set off Pavlovian screams of `HASH!' If you find them in
Xthe same sentence as `array', you're probably doing something
Xwrong.
X
X=Use Hashes for Sets
X
X* Consider finding the union and intersection of
Xtwo unique arrays @a and @b:
X
X foreach $e (@a) { $union{$e} = 1 }
X foreach $e (@b) {
X if ( $union{$e} ) { $isect{$e} = 1 }
X $union{$e} = 1;
X }
X @union = keys %union;
X @isect = keys %isect;
X
X* This would be more idiomatically written as:
X
X foreach $e (@a, @b) { $union{$e}++ && $isect{$e}++ }
X @union = keys %union;
X @isect = keys %isect;
X
X=Use Hashes for the First Time
X
X* A hash is a good way to keep track of whether
Xyou've done something before.
X
X* Embrace the C<... unless $seen{$item}++> notation:
X
X %seen = ();
X foreach $item (genlist()) {
X func($item) unless $seen{$item}++;
X }
X
X=Use Hashes of Records, not Parallel Arrays
X
X* Learn to use hashes of records, and maintain array or
Xhashes of these records, rather than using parallel
Xarrays. Don't do this:
X
X $age{"Jason"} = 23;
X $dad{"Jason"} = "Herbert";
X
XWhen you should do:
X
X $people{"Jason"}{AGE} = 23;
X $people{"Jason"}{DAD} = "Herbert";
X
XOr even: (note use of C<for> here)
X
X for $his ($people{"Jason"}) {
X $his->{AGE} = 23;
X $his->{DAD} = "Herbert";
X }
X
XBut think B<very> carefully before writing this:
X
X @{ $people{"Jason"} }{"AGE","DAD"} = (23, "Herbert");
X
X=Use $_ in Short Code
X
X* Contrary to beginners' belief, $_ improves legibility.
XCompare:
X
X while ($line = <>) {
X next if $line =~ /^#/;
X $line =~ s/left/right/g;
X $line =~ tr/A-Z/a-z/;
X print "$ARGV:";
X print $line;
X }
X
Xwith:
X
X while ( <> ) {
X next if /^#/;
X s/left/right/g;
X tr/A-Z/a-z/;
X print "$ARGV:";
X print;
X }
X
X=Use foreach() Loops
X
X* A C<foreach> loop's implicit aliasing and localizing
Xcan make for a powerful construct:
X
X foreach $e (@a, @b) { $e *= 3.14159 }
X
X for (@lines) {
X chomp;
X s/fred/barney/g;
X tr[a-z][A-Z];
X }
X
X* Remember you can copy and modify all at once:
X
X foreach $n (@square = @single) { $n **= 2 }
X
X* You can use hash slices to modify hash values, too:
X
X # trim whitespace in the scalar, the array,
X # and all the values in the hash
X foreach ($scalar, @array, @hash{keys %hash}) {
X s/^\s+//;
X s/\s+$//;
X }
X
X=Avoid Byte Processing
X
X* C programmers often try to process strings a byte at a time.
XDon't do that! Perl makes it easy to take data in big bites.
X
X* Don't use C<getc>. Grab the whole line and operate on it all at once.
X
X* Even operations traditionally done a char at a time in C, like
Xlexing, should be done differently. For example:
X
X @chars = split //, $input;
X while (@chars) {
X $c = shift @chars;
X # State machine;
X }
X
XIs far too low level. Try something more like:
X
X sub parse_expr {
X local $_ = shift;
X my @tokens = ();
X my $paren = 0;
X my $want_term = 1;
X
X while (length) {
X s/^\s*//;
X
X if (s/^\(//) {
X return unless $want_term;
X push @tokens, '(';
X $paren++;
X $want_term = 1;
X next;
X }
X
X if (s/^\)//) {
X return if $want_term;
X push @tokens, ')';
X if ($paren < 1) {
X return;
X }
X --$paren;
X $want_term = 0;
X next;
X }
X
X if (s/^and\b//i || s/^&&?//) {
X return if $want_term;
X push @tokens, '&';
X $want_term = 1;
X next;
X }
X
X if (s/^or\b//i || s/^\|\|?//) {
X return if $want_term;
X push @tokens, '|';
X $want_term = 1;
X next;
X }
X
X if (s/^not\b//i || s/^~// || s/^!//) {
X return unless $want_term;
X push @tokens, '~';
X $want_term = 1;
X next;
X }
X
X if (s/^(\w+)//) {
X push @tokens, '&' unless $want_term;
X push @tokens, $1 . '()';
X $want_term = 0;
X next;
X }
X
X return;
X
X }
X return "@tokens";
X }
X
X=Avoid Symbolic References
X
X* Beginners often think they want to have a variable contain the name
Xof a variable.
X
X $fred = 23;
X $varname = "fred";
X ++$varname; # $fred now 24
X
X* This works sometimes, but is a bad idea. They B<only work on global
Xvariables>. Global variables are bad because they can easily collide
Xaccidentally.
X
X* They do not work under the use strict pragma
X
X* They are not true references and consequently are not reference
Xcounted or garbage collected.
X
X* Use a hash or a real reference instead.
X
X=Using A Hash Instead of $$name
X
X* Using a variable to contain the name of another variable always
Xsuggests that perhaps someone doesn't understand hashes very well.
XWhile you could write this:
X
X $name = "fred";
X $$name{WIFE} = "wilma"; # set %fred
X
X $name = "barney"; # set %barney
X $$name{WIFE} = "betty";
X
XBetter to write:
X
X $folks{"fred"} {WIFE} = "wilma";
X $folks{"barney"}{WIFE} = "betty";
X
X=Avoid Testing eof
X
X* Don't use this: (deadlock)
X
X while (!eof(STDIN)) {
X statements;
X }
X
X* Use this instead:
X
X while (<STDIN>) {
X statements;
X }
X
X* Prompting while not eof can be a hassle. Try this:
X
X $on_a_tty = -t STDIN && -t STDOUT;
X sub prompt { print "yes? " if $on_a_tty }
X for ( prompt(); <STDIN>; prompt() ) {
X statements;
X }
X
X=Avoid Gratuitous Backslashes
X
X* Perl lets you choose your own delimiters on quotes and
Xpatterns to avoid Leaning Toothpick Syndrome. Use them.
X
X m#^/usr/spool/m(ail|queue)#
X
X qq(Moms said, "That's all, $kid.")
X
X tr[a-z]
X [A-Z];
X
X s { / }{::}gx;
X s { \.p(m|od)$ }{}x;
X
X=Reduce Complexity
X
X* But place C<next> and C<redo> near the top of the loop when possible.
X
X* Use C<unless> and C<until>.
X
X* But don't use C<unless ... else ...>
X
X* Escape the tyranny of Pascal. Don't go through silly contortions to
Xexit a loop or a function only at the bottom. Don't write:
X
X while (C1) {
X if (C2) {
X statement;
X if (C3) {
X statements;
X }
X } else {
X statements;
X }
X }
X
X=Reduce Complexity (solution)
X
X* Write this instead:
X
X while (C1) {
X unless (C2) {
X statement;
X next;
X }
X statements;
X next unless C3;
X statements;
X }
X
X* Or perhaps even:
X
X while (C1) {
X statement, next unless C2;
X statements;
X next unless C3;
X statements;
X }
X
X
X=Loop Hoisting
X
X* Hoist repeated code out of blocks:
X
XBefore:
X
X if (...) {
X X; Y;
X } else {
X X; Z;
X }
X
XAfter:
X
X X;
X if (...) {
X Y;
X } else {
X Z;
X }
X
X=Break Complex Tasks Up
X
X* Break subroutines into manageable pieces.
X
X* Don't try to fit everything into one regex.
X
X* Play with your ARGV:
X
X # program expects envariables
X @ARGV = keys %ENV unless @ARGV;
X
X # program expects source code
X @ARGV = glob("*.[chyC]") unless @ARGV;
X
X # program tolerates gzipped files
X # from PCB 16.6
X @ARGV = map { /^\.(gz|Z)$/ ? "gzip -dc $_ |" : $_ } @ARGV;
X
X=Break Programs into Separate Processes
X
X* Learn how to use the special forms of C<open>.
X(See also I<tgent> in TSA).
X
X # from PCB 16.5
X head(100);
X sub head {
X my $lines = shift || 20;
X return if $pid = open(STDOUT, "|-");
X die "cannot fork: $!" unless defined $pid;
X while (<STDIN>) {
X print;
X last if --$lines < 0;
X }
X exit;
X }
X
X=Data-Oriented Programming
X
X* Data structures are more important than code.
X
X* Rob Pike says: `Data dominates. If you've chosen the right data
Xstructures and organized things well, the algorithms will almost
Xalways be self-evident. Data structures, not algorithms, are central to
Xprogramming. (See Brooks p. 102.)'
X
X* Capture regularity with data, irregularity with code. (Kernighan)
X
X* If you see similar functionality in two places, unify it.
X That is called a `subroutine'.
X
X* Consider making a hash of function pointers to represent
Xa state table or switch statement.
X
X=Configuration Files
X
X* If you need a config file, load it with C<do>.
X
X* This gives you full Perl power.
X
X # from PCB 8.16
X $APPDFLT = "/usr/local/share/myprog";
X do "$APPDFLT/sysconfig.pl";
X do "$ENV{HOME}/.myprogrc";
X
X #in config file
X $NETMASK = '255.255.255.0';
X $MTU = 0x128;
X $DEVICE = 'cua1';
X $RATE = 115_200;
X
X* See I<clip> and I<cliprc> file in Tom's Script Archive
Xat http://www.perl.com/CPAN/authors/id/TOMC/scripts/
X
X=Functions as Data
X
X* Use function pointers as function arguments or in data structures:
X
X # from MxScreen in TSA (see also PCB 19.12)
X %State_Table = (
X Initial => \&show_top,
X Execute => \&run_query,
X Format => \&get_format,
X Login => \&resister_login,
X Review => \&review_selections,
X Sorting => \&get_sorting,
X Wizard => \&wizards_only,
X );
X
X foreach my $state (sort keys %State_Table) {
X my $function = $State_Table{$state};
X my $how = ($action == $function)
X ? SCREEN_DISPLAY
X : SCREEN_HIDDEN;
X $function->($how);
X }
X
X=Closures
X
X* Clone similar functions using closures.
X
X # from MxScreen in TSA
X no strict 'refs';
X for my $color (qw[red yellow orange green blue purple violet]) {
X *$color = sub { qq<<FONT COLOR="\U$color\E">@_</FONT>> };
X }
X undef &yellow; # lint happiness
X *yellow = \&purple; # function aliasing
X
X* Or similarly:
X
X # from psgrep (in TSA, or PCB 1.18)
X my %fields;
X my @fieldnames = qw(FLAGS UID PID PPID PRI NICE SIZE
X RSS WCHAN STAT TTY TIME COMMAND);
X
X for my $name (@fieldnames) {
X no strict 'refs';
X *$name = *{lc $name} = sub () { $fields{$name} };
X }
X
X=Learn to Switch with for
X
X* Though Perl has no built-in switch statement, this is
Xnot a hardship but an opportunity.
X
X* It's easy to build one. The word `for' is sometimes
Xpronounced `switch'.
X
X SWITCH: for ($where) {
X /In Card Names/ && do { push @flags, '-e'; last; };
X /Anywhere/ && do { push @flags, '-h'; last; };
X /In Rulings/ && do { last; };
X die "unknown value for form variable where: `$where'";
X }
X
X* Like a series of C<elsif>s, a switch should B<always> have a default
Xcase, even if the default case `can't happen'.
X
X=Switch by Using do{} Creatively
X
X* Another interesting approach to a switch statement is arrange for a do
Xblock to return the proper value:
X
X $amode = do {
X if ($flag & O_RDONLY) { "r" } # XXX: isn't this 0?
X elsif ($flag & O_WRONLY) { ($flag & O_APPEND) ? "a" : "w" }
X elsif ($flag & O_RDWR) {
X if ($flag & O_CREAT) { "w+" }
X else { ($flag & O_APPEND) ? "a+" : "r+" }
X }
X };
X
X=Switch with for via && and ||
X
X* Be careful that the RHS of && is always true.
X
X $dir = 'http://www.wins.uva.nl/~mes/jargon';
X for ($ENV{HTTP_USER_AGENT}) {
X $page = /Mac/ && 'm/Macintrash.html'
X || /Win(dows )?NT/ && 'e/evilandrude.html'
X || /Win|MSIE|WebTV/ && 'm/MicroslothWindows.html'
X || /Linux/ && 'l/Linux.html'
X || /HP-UX/ && 'h/HP-SUX.html'
X || /SunOS/ && 's/ScumOS.html'
X || 'a/AppendixB.html';
X }
X
X=Switch Using for and do{} Even More Creatively
X
X* Sometimes, aesthetics counts. :-)
X
X for ($^O) {
X *struct_flock = do {
X
X /bsd/ && \&bsd_flock
X ||
X /linux/ && \&linux_flock
X ||
X /sunos/ && \&sunos_flock
X ||
X die "unknown operating system $^O, bailing out";
X };
X }
X
X=The Care and Feeding of Modules
X
X* Document your modules with Pod. Test your pod with I<pod2man>
Xand with I<pod2html>.
X
X* Use the Carp module's C<carp>, C<croak>, and C<confess>
Xroutines, not C<warn> and C<die>.
X
X* Well written modules seldom require C<::>. Users should
Xget at module contents using an import or a class method call.
X
X* Traditional modules are fine. Don't jump to full objects just because
Xit's considered cool. Do it only when the occasion obviously calls
Xfor it.
X
X* Access to objects should only be through object methods.
X
X* Object methods should themselves access class data through pointers
Xon the object.
X
X=Patches
X
X* When you're working on someone else's code,
Xtry to follow their lead.
X
X* Avoid reformatting text so it doesn't create
Xspuriously large diffs.
X
X* Converting tabs to spaces may be necessary to cope
Xwith the evil folk who set hardware tabs to something
Xother than 8, or who have custom tab stops. B<Don't do that.>
X
X
X=From Perlstyle (part 1)
X
X* 4-column indent. Make your editor help you! [DEMO]
X* Opening curly on same line as keyword, if possible; otherwise line up.
X* Space before the opening curly of a multi-line BLOCK.
X* One-line BLOCK may be put on one line, including curlies.
X* No space before the semicolon.
X* Semicolon omitted in `short' one-line BLOCK.
X* Space around most operators.
X* Space around a `complex' subscript (inside brackets).
X* Blank lines between chunks that do different things.
X* Uncuddled elses.
X
X=From Perlstyle (part 2)
X
X* No space between function name and its opening parenthesis.
X* Space after each comma.
X* Long lines broken after an operator (except `and' and `or').
X* Space after last parenthesis matching on current line.
X* Line up corresponding items vertically.
X* Omit redundant punctuation as long as clarity doesn't suffer.
X* Use here documents instead of repeated print() statements.
X* Line up corresponding things vertically, especially if it'd be too
Xlong to fit on one line anyway.
SHAR_EOF
: || $echo 'restore of' 'perlpoint/Style.pp' 'failed'
fi
# ============= perlpoint/Intro.pp ==============
if test -f 'perlpoint/Intro.pp' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'perlpoint/Intro.pp' '(file already exists)'
else
$echo 'x -' extracting 'perlpoint/Intro.pp' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'perlpoint/Intro.pp' &&
X=Programming in the Large
X
XRelease 5 of Perl provides the fundamentals necessary
Xfor safely programming larger and more elaborate
Xprojects than was previously possible in perl4.
XThese features include:
X
X* Lexical scoped variables via C<my()>
X
X* Compiler directives for careful programming
X
X* Namespace protection for modules
X
X* Transparent access to C code
X
X* Exception Handling
X
X* References
X
X* Anonymous data and function types
X
X* Object-oriented features, including Representational encapsulation,
Xmethod calls, constructors and destructors, and inheritance
X
X= Object-Oriented Features
X
X* Perl has a number of object-oriented features available to it.
XYou might ask why this was even done. Initially, it was so that one
Xcould embed Perl in C++ code and have concepts that mapped properly.
X
X* The model used by Perl differs from that of C++, largely because of
XLarry's experiences of working with C++ daily over the last few years.
X
X* A side-effect is that certain problems really are better expressed
Xusing an object-oriented paradigm -- just not so many as the marketing
Xhype would have you believe. :-)
X
X* Many of the newer 3rd-party modules, especially for Tk, the Web, and
Xdatabase access, are all object-oriented.
X
X=Object-Oriented Programming
X
X* Doing OOP in Perl first requires that you
Xunderstand some underlying facilities.
X
X* I<Classes> are built using I<references>
Xplus I<modules>.
X
X* I<Modules> are built using I<packages> plus I<exporting>.
X
X* A I<package> is a separate namespace.
X
X* A I<symbol table> holds the names of a package's variables and
Xfunctions.
X
X* A I<library> is a collection of subroutine definitions and code,
Xoften stored in a I<somelib.pl> file.
X
X* A I<module> is a library following special packaging rules and stored
Xin a I<SomeLib.pm> file.
X
SHAR_EOF
: || $echo 'restore of' 'perlpoint/Intro.pp' 'failed'
fi
# ============= perlpoint/slidemacs ==============
if test -f 'perlpoint/slidemacs' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'perlpoint/slidemacs' '(file already exists)'
else
$echo 'x -' extracting 'perlpoint/slidemacs' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'perlpoint/slidemacs' &&
X.nr L 2
X'\" macro package for making foils
X'if \n(mo-0 .ds mo Jan
X'if \n(mo-1 .ds mo Feb
X'if \n(mo-2 .ds mo Mar
X'if \n(mo-3 .ds mo Apr
X'if \n(mo-4 .ds mo May
X'if \n(mo-5 .ds mo Jun
X'if \n(mo-6 .ds mo Jul
X'if \n(mo-7 .ds mo Aug
X'if \n(mo-8 .ds mo Sept
X'if \n(mo-9 .ds mo Oct
X'if \n(mo-10 .ds mo Nov
X'if \n(mo-11 .ds mo Dec
X'ds DA \\*(mo \n(dy, 19\n(yr
X'na
X'ie \*(.Tcan \{\
X'fp 4 vS
X'ft B
X'ps 22
X'ds FT B
X'\}
X'el \{\
X'ft PB
X'ps 23
X'ds FT (PB
X'\}
X'vs 23
X'\" Parameters:
X'nr PW 11i \" PW=paper width
X'nr PH 8.5i \" PH=paper height
X'nr MB 1i \" MB=margin border
X'nr MT 0.5i \" MT=margin text
X'nr BW \n(PWu-\n(MBu-\n(MBu \" BW=border width
X'nr TW \n(BWu-\n(MTu-\n(MTu \" TW=text width
X.nr C 0.5i \" C =corner radius
X'nr PT \n(MBu+\n(MTu \" PT=page offset for text
X'nr BB \n(PHu-\n(MBu \" BB=bottom of box
X'\" 0.7i is the amount the logo sticks up over line
X'nr CH 0.6i \" CH=height of logo (above base)/2
X'nr BT \n(BBu-\n(CHu-1v \" BT=bottom of text
X'if \nL=1 \{\
X' tm Setting bottom line for no logo
X' nr BT \n(BBu-1v \" BT=bottom of text (no logo)
X'\}
X'nr CW 2.3i \" CW=width of logo
X' \" MW=width of middle title
X' \" DW=width of date
X'pl \n(PHu
X'll \n(TWu
X'lt \n(Twu
X'ev 1
X'll \n(TWu
X'lt \n(TWu
X'ev
X'po \n(PTu
X'wh \n(BTu fa
X.de au
X.if \\$2FIRST .M4
X'ds ff "'' \fR\&\\$1 ' \\*(DA\fP '"
X'ds RF \&\\$1
X.if \\$2FIRST .nn
X..
X.de hd \" header
X'sp \\n(MBu
X.\"'sp \\n(MTu
X..
X'wh 0 hd
X'ds ff "''' \*(DA '"
X'de Ft \" footer
X'ds ff \&\\$1
X..
X.de fa
X.ch fa
X.ev 1
X.vs 0
X.sp |\\n(MBu
X.po \\n(MBu
X.nr W \\n(BWu-\\nCu-\\nCu \" actual width for box drawing
X.nr H \\n(PHu-\\n(MBu-\\n(MBu-\\nCu-\\nCu \" actual height for box
X'ie !\\*(RF 'nr MW \w'\s9 \\*(RF \s0'u
X'el 'nr MW 0
X'nr DW \w'\s9 \\*(DA \s0'u \" DW=width of date
X.nr a1 ((\\n(BWu-\\n(MWu)/2u)-\\nCu \" width of half of bottom straight line
X.nr a2 \\n(a1u-\\n(CWu
X.nr a3 \\n(a1u-\\n(DWu
X.ps 36
X.ds Z \h'\\n(CWu'
X.if \\nL .ds Z \D'l \\n(CWu 0'
X.if \\n(NB=0 \{\
X.\" \D't 12u'\v'\\nCu'\D'l 0 \\nHu'\D'a \\nCu 0 0 \\nCu'\\*Z\D'l \\n(a2u 0'\h'\\n(MWu'\D'l \\n(a3u 0'\h'\\n(DWu'\D'a 0 -\\nCu \\nCu 0'\D'l 0 -\\nHu'\D'a -\\nCu 0 0 -\\nCu'\D'l -\\nWu 0'\D'a 0 \\nCu -\\nCu 0'
X\v'\\nCu'\D'l 0 \\nHu'\D'a \\nCu 0 0 \\nCu'\\*Z\D'l \\n(a2u 0'\h'\\n(MWu'\D'l \\n(a3u 0'\h'\\n(DWu'\D'a 0 -\\nCu \\nCu 0'\D'l 0 -\\nHu'\D'a -\\nCu 0 0 -\\nCu'\D'l -\\nWu 0'\D'a 0 \\nCu -\\nCu 0'
X.br
X.\}
X.ps
X.po
X.sp |\\n(BBu
X'ps 9
X.sp 3p \" to center on the line instead of have baseline on line
X.if \\n(NB=0 'tl \\*(ff
X'ps
X.if !\\nL \{\
X. sp |\\n(BBu-\\n(CHu+0.15i
X. ft H
X. ps 14
X. vs 15
X. nf
X. po +.05i
XRocky
XMountain
XTechnology
XCenter
X. po
X. fi
X. ps
X. vs
X. ft
X. po +1i
X. sp |\\n(BBu
X. sp 0.45i \" makes logo line up correctly on baseline
X\D'Z 1.5i 1.5i'
X. sp -1
X\X'ps file camel.ps'\c
X. po
X.\}
X.vs
X.if \\nP \{\
X. sp |\\n(BBu
X. sp 0.5i
X. po 0.4i
X. nr QQ \\n(PW-0.4i-0.4i
X. lt \\n(QQu
X. tl '''\f(CW\s14Slide %\s0\fP'
X. lt
X. po
X.\}
X'bp
X.ev
X.wh \\n(BTu fa
X..
X.de c
X.in 0
X.na
X.ce
X.if !\\$1 \&\\$1
X..
X.de 1
X.in \w' 'u
X.ti -\w' 'u
X.if !\\$1 \&\\$1
X..
X.de 2
X.in 0.5i
X.ti -\w'\(bu\h0.15i'u
X\(bu\h0.15i\c
X.if !\\$1 \&\\$1
X..
X.de 3
X.in 1.0i
X.\" TSC 'if \*(.Tcan .ft vS
X.\" TSC .ti -\w\(ci\h'0.15i'u
X.\" TSC \(ci\h'0.15i'\c
X.\" TSC 'ie \*(.Tcan .ft B
X.\" TSC 'el .ft PB
X.ti -\w'\(bu\h0.15i'u
X\(bu\h0.15i\c
X.if !\\$1 \&\\$1
X..
X.de 4
X.in 1.5i
X.ti -\w'\s(26\fB\(sq\fP\s0\h0.15i'u
X\s(26\fB\v'0.02i'\(sq\v'-0.02i'\fP\s0\h'0.15i'\c
X.if !\\$1 \&\\$1
X..
X.de n
X.in \\$1
X.ti -\w\\$2
X\&\\$2
X.sp -1
X.if !\\$3 \&\\$3
X..
X.ie \*(.Tcan .ds FF (TA
X.el .ds FF (CB
X.de b
X.ie \*(.Tcan \{\
X.ft TA
X.ps 20
X.\}
X.el \{\
X.ft CB
X.ps 23
X.\}
X.nr X 8*\w' 'u
X.ta +\\nXu +\\nXu +\\nXu +\\nXu +\\nXu +\\nXu +\\nXu +\\nXu
X.nf
X..
X.de e
X.\" TSC 'ie \*(.Tcan \{\
X.ft B
X.ps 23
X.\" TSC .\}
X.\" TSC 'el \{\
X.\" TSC .ft PB
X.\" TSC .ps 23
X.\" TSC .\}
X.vs 23
X.fi
X..
X.de CX
X.ie \*(.Tcan .ds ZZ \\f(CX\\s(20
X.el .ds ZZ \\f(BI\\s23
X\&\\*(ZZ\\$1\fP\s0\\$2\& \\$3 \\$4 \\$5 \\$6
X..
X.de TA
X.ie \*(.Tcan .ds ZZ \\f(TA\\s(20
X.el .ds ZZ \\f(CB\\s23
X\\*(ZZ\c
X..
X.de ET
X'ie \*(.Tcan \{\
X'ft B
X'ps 22
X'\}
X'el \{\
X'ft PB
X'ps 23
X'\}
X'vs 23
X'fi
X..
X.de BI
X\\f(BI\\$1\fP\\$2
X..
X.de SM
X\\s-2\\$1\\s0\\$2
X..
X.de UR
X.b
X.sz -6
X\\$1
X.sz +6
X.sp .25
X.e
X..
X.de MP
X\\f(BI\\$1\\fP\|(\\$2)
X..
X.de U2
X'2
X\\$1
X.br
X.in +2n
X'UR "\\$2"
X.in -2n
X.br
X..
X.de T
X.\" TSC .ie \*(.Tcan .ds ZZ \\f(TA\\s(20
X.\" TSC .el .ds ZZ \\f(CB\\s(23
X.ds ZZ \f(CB\s20
X\&\\*(ZZ\\$1\fP\s0\\$2\& \\$3 \\$4 \\$5 \\$6
X..
X.na
X.hy 0
X.de sz
X.ps \\$1
X.vs \\$1
X..
X'\"#ident "@(#)pic:PS-PEmacros 1.4"
X'\" Copyright (c) 1984 AT&T
X'\" All Rights Reserved
X'\" THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
X'\" The copyright notice above does not evidence any actual
X'\" or intended publication of such source code.
X.de PS \" start picture
X. \" $1 is height, $2 is width, both in inches
X.if t .sp .3
X.in (\\n(.lu-\\$2)/2u
X.ne \\$1
X..
X.de PE \" end of picture
X.in
X.if t .sp .6
X..
X.de nn
X.tm Slide \\*(RF starts on page \\n%
X..
X.de M4
X.br
X.nr NB 1
X'ds ff "''' \*(DA '"
X'ds RF\"
X.nr QQ \\n%-(\\n%/4*4)
X.if !'1'\\n(QQ' .bp
X.nr QQ \\n%-(\\n%/4*4)
X.if !'1'\\n(QQ' .bp
X.nr QQ \\n%-(\\n%/4*4)
X.if !'1'\\n(QQ' .bp
X.nr QQ \\n%-(\\n%/4*4)
X.if !'1'\\n(QQ' .ab M4 left me on page \\n%????????
X.nr NB 0
X..
X.de HH
X.di NT
X.ps 60
X.vs 60
X\\$1
X.br
X.ps
X.vs
X.di
X.nr Uw \\n(dlu+0.5i
X.nr Uh \\n(dnu+0.2i
X.sp |3.35i
X.nr QQ (\\n(.lu-\\n(Uwu)/2u
X\h'\\n(QQu'\D'l \\n(Uwu 0'\D'l 0 \\n(Uhu'\D'l -\\n(Uwu 0'\D'l 0 -\\n(Uhu'
X.sp 0.45i
X.ce
X.NT
X..
X.br
X.nr P 1 \" page numbers on
X.\" .nr L 0 \" logos on
X.ds C+ C\v'-.1v'\h'-2p'\s-2+\h'-2p'+\s0\v'.1v'\h'-1p'
X.b
X
X.e
SHAR_EOF
: || $echo 'restore of' 'perlpoint/slidemacs' 'failed'
fi
# ============= perlpoint/ppages ==============
if test -f 'perlpoint/ppages' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'perlpoint/ppages' '(file already exists)'
else
$echo 'x -' extracting 'perlpoint/ppages' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'perlpoint/ppages' &&
X#!/usr/bin/perl -p
X$_=".au \"$ARGV - ".++$count."\"\n" if /^\.au/;
X$count = 0 if eof;
SHAR_EOF
: || $echo 'restore of' 'perlpoint/ppages' 'failed'
fi
# ============= perlpoint/Makefile ==============
if test -f 'perlpoint/Makefile' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'perlpoint/Makefile' '(file already exists)'
else
$echo 'x -' extracting 'perlpoint/Makefile' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'perlpoint/Makefile' &&
XLINKS=links
X
Xall: html roff ps
X
Xhtml: Intro Style
X
Xroff: Intro.nr Style.nr
X
Xps: roff
X ppages title.nr Intro.nr Style.nr | tbl | psroff -r -Tps -t slidemacs - > TALK.ps
X
XIntro.nr: Intro.pp
X pp2roff Intro.pp > Intro.nr
X
XStyle.nr: Style.pp
X pp2roff Style.pp > Style.nr
X
XIntro: Intro.pp
X @mkdir Intro 2>/dev/null || true
X cd Intro; perl ../pp2html -${LINKS} -class "Perl Point Demo" -section "Intro" ../Intro.pp
X
XStyle: Style.pp
X @mkdir Style 2>/dev/null || true
X cd Style; perl ../pp2html -${LINKS} -class "Perl Point Demo" -section "Style" ../Style.pp
X
X
Xclean:
X rm -rf Intro.nr Style.nr TALK.ps Style Intro
SHAR_EOF
: || $echo 'restore of' 'perlpoint/Makefile' 'failed'
fi
# ============= perlpoint/title.nr ==============
if test -f 'perlpoint/title.nr' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'perlpoint/title.nr' '(file already exists)'
else
$echo 'x -' extracting 'perlpoint/title.nr' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'perlpoint/title.nr' &&
X.nr % 0
X.nr L 1
X.nr P 1
X.au "Talk: This is it"
X.ce 10
X.sp .5i
X.sz 36
XWhat We're Doing
X.sz 18
X.sp .5i
X.sp 2.5
X\s18\f(BIJohn Smith
X<john@mail.smith.com\fB>
X\s10Copyright 1999\s24
X.sp .5i
X\f(BIThere's more than one way to do it!\fP
X.\" ===========================================================================
X.b
X.e
SHAR_EOF
: || $echo 'restore of' 'perlpoint/title.nr' 'failed'
fi
rm -fr _sh20212
exit 0
--
Supercomputer - a computer that can complete an endless loop in under 5 minutes
------------------------------
Date: Sat, 6 Mar 1999 18:03:28 -0000
From: "Rafala" <rafala@loyolanet.campus.mci.net>
Subject: Sub calls: how can I do this?
Message-Id: <7bsbti$fug$1@news.campus.mci.net>
How can I do this?
Suppose my script uses a module with a slew of subs in it. But the script
doesn't know which of those subs to call until the sub name is passed via an
argument or read in through a data file.
I was hoping that I could put the sub name into a scaler and use that in the
call, e.g.:
$yyy = $ARGV[0]; #the sub name was passed as an argument
@xxx = $yyy ("hello");
Of course, it looks kind of silly now that I've tried it.
I hope I don't have to do something like
if ($ARGV[0] = "sub_1") {
@xxx = sub_1 ("hello");
} elsif ($ARGV[0] = "sub_2") {
@xxx = sub_2 ("hello");
} elsif ...
}
Can someone steer me in the right direction?
mike rafala
rafalam@cadmus.com
------------------------------
Date: Sat, 06 Mar 1999 14:30:51 -0800
From: grumetedapanair@hotmail.com ("Adrian Fiorinni")
Subject: Upload file without CGI.pm - possible?
Message-Id: <u0iE2.4088$xv.37621640@WReNphoon2>
Everything is possible in Perl...
under WinXX, u must set fiemode "binmode"
check the upload script at:
www.zonecoaster.com/Scripts/upload/index.html
it ***doesn't*** use CGI.pm
[]'s
*** Posted from RemarQ - http://www.remarq.com - Discussions Start Here (tm) ***
------------------------------
Date: 6 Mar 1999 23:23:30 -0000
From: Jonathan Stowe <gellyfish@btinternet.com>
Subject: Re: Upload file without CGI.pm - possible?
Message-Id: <7bsddi$2c9$1@gellyfish.btinternet.com>
On Sat, 06 Mar 1999 18:19:46 GMT Scott Porter wrote:
>
<snip>
> This all seems to work fine for a text file, but with binary, I just
> get a few characters and that's it! I'm assuming that Perl is interpreting
> some binary character as the EOF marker or something and closing the
> connection?
>
binmode() the read and write file handles then ... its doesnt matter for
text files and is always necessary for binary files on those systems that
distinguish between text and binary - a harmless no-op on those systems
that sensibly dont care.
> Anyway, Searching around I find most people use CGI.pm and having
> located it I tried to install it on my Win'98 machine (I'm currently
> using the sambar4.2 web server with its own version of Perl - reported
> to be version 5.004_02 for windows platform) but couldn't as I don't have
> "makemaker". Chances are I'm not going to be allowed to compile new perl
> modules on the server I'm setting up, and I really don't want to waste
> time writing a script that will not work on the "live" site, so is there
> a way to accept a binary file without CGI.pm?
>
Well sure you could do it without CGI.pm but why ? Since 5.004.04 CGI.pm
has been part of the standard distribution for Perl. I'm sure that your
server doesnt have to use 'its own version of Perl' and that you could
happily upgrade to the ActiveState version - of course that could raise
questions that would better be pursued in in one of the the groups
concerned with server matters.
Another matter is that because CGI.pm doesnt contain any binary elements
it can be installed on Windows without a compiler - you *do* have MakeMaker
believe me it is part of the Perl distribution and if your Perl is what used
to be the 'standard' Perl distribution for Win32 then you should have 'dmake'
which is a drop-in replacement for the 'make' referenced in the README file
for the module. If you dont have dmake then that can be obtained easily.
If all else fails then you could simply copy the CGI.pm file into some
suitable directory (preferably where your existing modules are) - if this
directory is not in @INC then you can always add it to @INC at compile
time by using the 'use lib' pragma :
use lib 'c:/blah/yadayada';
I'm sure some kind soul will provide you with some script that will do the
upload without CGI.pm but unless you *really* cant avoid it its not worth
the hassle.
/J\
--
Jonathan Stowe <jns@btinternet.com>
Some of your questions answered:
<URL:http://www.btinternet.com/~gellyfish/resources/wwwfaq.htm>
Hastings: <URL:http://www.newhoo.com/Regional/UK/England/East_Sussex/Hastings>
------------------------------
Date: 12 Dec 98 21:33:47 GMT (Last modified)
From: Perl-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Special: Digest Administrivia (Last modified: 12 Dec 98)
Message-Id: <null>
Administrivia:
Well, after 6 months, here's the answer to the quiz: what do we do about
comp.lang.perl.moderated. Answer: nothing.
]From: Russ Allbery <rra@stanford.edu>
]Date: 21 Sep 1998 19:53:43 -0700
]Subject: comp.lang.perl.moderated available via e-mail
]
]It is possible to subscribe to comp.lang.perl.moderated as a mailing list.
]To do so, send mail to majordomo@eyrie.org with "subscribe clpm" in the
]body. Majordomo will then send you instructions on how to confirm your
]subscription. This is provided as a general service for those people who
]cannot receive the newsgroup for whatever reason or who just prefer to
]receive messages via e-mail.
The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc. For subscription or unsubscription requests, send
the single line:
subscribe perl-users
or:
unsubscribe perl-users
to almanac@ruby.oce.orst.edu.
To submit articles to comp.lang.perl.misc (and this Digest), send your
article to perl-users@ruby.oce.orst.edu.
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.
The Meta-FAQ, an article containing information about the FAQ, is
available by requesting "send perl-users meta-faq". The real FAQ, as it
appeared last in the newsgroup, can be retrieved with the request "send
perl-users FAQ". Due to their sizes, neither the Meta-FAQ nor the FAQ
are included in the digest.
The "mini-FAQ", which is an updated version of the Meta-FAQ, is
available by requesting "send perl-users mini-faq". It appears twice
weekly in the group, but is not distributed in the digest.
For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V8 Issue 5077
**************************************