[9820] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 3413 Volume: 8

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Mon Aug 10 23:07:24 1998

Date: Mon, 10 Aug 98 20:02:32 -0700
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Mon, 10 Aug 1998     Volume: 8 Number: 3413

Today's topics:
    Re: use strict problem with indirect file variables ? <tchrist@mox.perl.com>
    Re: What is the purpose of Perl <uri@sysarch.com>
        Special: Digest Administrivia (Last modified: 12 Mar 98 (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: 11 Aug 1998 02:31:34 GMT
From: Tom Christiansen <tchrist@mox.perl.com>
Subject: Re: use strict problem with indirect file variables ?
Message-Id: <6qoae6$mjm$1@csnews.cs.colorado.edu>

 [courtesy cc of this posting sent to cited authors via email]

In comp.lang.perl.misc, sowmaster@juicepigs.com (Bob Trieger) writes:
:phil@ackltd.demon.co.uk (Phil Taylor) wrote:

:-> $handle = "MYFILE";
:-> open ($handle, "<file1");
:
:ahhh?? Did  ` my $handle = "MYFILE" '  ever cross your mind?

Did trying what you wrote every cross your mind?  It doesn't work:

    Can't use string ("MYFILE") as a symbol ref while "strict refs" in use 

While use strict is in effect, you can't use symbolic references.  That's
what you're trying to do.

I don't understand why the original posted thought he needn't to resort
to indirect filehandles in the upper-level code merely to pass the thing
to a lower-level function.

This should work:

    open(MYFILE, "< file1") || die "can't open file1: $!";
    locker(*MYFILE);
    sub locker {
	my $fh = shift;
	flock($fh, 2);
    } 

or this:

    open(MYFILE, "< file1") || die "can't open file1: $!";
    locker(*MYFILE);
    sub locker {
	local *FH = shift;
	flock(FH, 2);
    } 

Oh heck, I might as well spam the group with documentation.
It's the only way anybody's going to read it.
 
Of course, this question will be probably asked twice more in rapid
succession.  No matter how often I explain, how often I post, how often
others explain, the FAQs will be ignored.  Grrrr...

--tom

/* 
 * BEGIN EXCERPT FROM PERLFAQ5 
 */

=head2 How can I make a filehandle local to a subroutine?  How do I pass
    filehandles between subroutines?  How do I make an array of filehandles?

The fastest, simplest, and most direct way is to localize the typeglob
of the filehandle in question:

    local *TmpHandle;

Typeglobs are fast (especially compared with the alternatives) and
reasonably easy to use, but they also have one subtle drawback.  If you
had, for example, a function named TmpHandle(), or a variable named
%TmpHandle, you just hid it from yourself.

    sub findme {
        local *HostFile;
	open(HostFile, "</etc/hosts") or die "no /etc/hosts: $!";
	local $_;		# <- VERY IMPORTANT
        while (<HostFile>) {
	    print if /\b127\.(0\.0\.)?1\b/;
	}
	# *HostFile automatically closes/disappears here
    }

Here's how to use this in a loop to open and store a bunch of
filehandles.  We'll use as values of the hash an ordered
pair to make it easy to sort the hash in insertion order.

    @names = qw(motd termcap passwd hosts);
    my $i = 0;
    foreach $filename (@names) {
	local *FH;
	open(FH, "/etc/$filename") || die "$filename: $!";
        $file{$filename} = [ $i++, *FH ];
    }

    # Using the filehandles in the array
    foreach $name (sort { $file{$a}[0] <=> $file{$b}[0] } keys %file) {
        my $fh = $file{$name}[1];
        my $line = <$fh>;
        print "$name $. $line";
    }

For passing filehandles to functions, the easiest way is to 
prefer them with a star, as in func(*STDIN).  See L<perlfaq7/"Passing
Filehandles"> for details.

If you want to create many, anonymous handles, you should check out the
Symbol, FileHandle, or IO::Handle (etc.) modules.  Here's the equivalent
code with Symbol::gensym, which is reasonably light-weight:

    foreach $filename (@names) {
	use Symbol;
	my $fh = gensym();
	open($fh, "/etc/$filename") || die "open /etc/$filename: $!";
        $file{$filename} = [ $i++, $fh ];
    }

Or here using the semi-object-oriented FileHandle, which certainly isn't
light-weight:

    use FileHandle;

    foreach $filename (@names) {
        my $fh = FileHandle->new("/etc/$filename") or die "$filename: $!";
        $file{$filename} = [ $i++, $fh ];
    }

Please understand that whether the filehandle happens to be a (probably
localized) typeglob or an anonymous handle from one of the modules,
in no way affects the bizarre rules for managing indirect handles.
See the next question.

=head2 How can I use a filehandle indirectly?

An indirect filehandle is using something other than a symbol
in a place that a filehandle is expected.  Here are ways
to get those:

    $fh =   SOME_FH;       # bareword is strict-subs hostile
    $fh =  "SOME_FH";      # strict-refs hostile; same package only
    $fh =  *SOME_FH;       # typeglob
    $fh = \*SOME_FH;       # ref to typeglob (bless-able)
    $fh =  *SOME_FH{IO};   # blessed IO::Handle from *SOME_FH typeglob

Or to use the C<new> method from the FileHandle or IO modules to
create an anonymous filehandle, store that in a scalar variable,
and use it as though it were a normal filehandle.

    use FileHandle;
    $fh = FileHandle->new();

    use IO::Handle;                     # 5.004 or higher
    $fh = IO::Handle->new();

Then use any of those as you would a normal filehandle.  Anywhere that
Perl is expecting a filehandle, an indirect filehandle may be used
instead. An indirect filehandle is just a scalar variable that contains
a filehandle.  Functions like C<print>, C<open>, C<seek>, or the functions or
the C<E<lt>FHE<gt>> diamond operator will accept either a read filehandle
or a scalar variable containing one:

    ($ifh, $ofh, $efh) = (*STDIN, *STDOUT, *STDERR);
    print $ofh "Type it: ";
    $got = <$ifh>
    print $efh "What was that: $got";

Of you're passing a filehandle to a function, you can write
the function in two ways:

    sub accept_fh {
        my $fh = shift;
        print $fh "Sending to indirect filehandle\n";
    }

Or it can localize a typeglob and use the filehandle directly:

    sub accept_fh {
        local *FH = shift;
        print  FH "Sending to localized filehandle\n";
    }

Both styles work with either objects or typeglobs of real filehandles.
(They might also work with strings under some circumstances, but this
is risky.)

    accept_fh(*STDOUT);
    accept_fh($handle);

In the examples above, we assigned the filehandle to a scalar variable
before using it.  That is because only simple scalar variables,
not expressions or subscripts into hashes or arrays, can be used with
built-ins like C<print>, C<printf>, or the diamond operator.  These are
illegal and won't even compile:

    @fd = (*STDIN, *STDOUT, *STDERR);
    print $fd[1] "Type it: ";                           # WRONG
    $got = <$fd[0]>                                     # WRONG
    print $fd[2] "What was that: $got";                 # WRONG

With C<print> and C<printf>, you get around this by using a block and
an expression where you would place the filehandle:

    print  { $fd[1] } "funny stuff\n";
    printf { $fd[1] } "Pity the poor %x.\n", 3_735_928_559;
    # Pity the poor deadbeef.

That block is a proper block like any other, so you can put more
complicated code there.  This sends the message out to one of two places:

    $ok = -x "/bin/cat";                
    print { $ok ? $fd[1] : $fd[2] } "cat stat $ok\n";
    print { $fd[ 1+ ($ok || 0) ]  } "cat stat $ok\n";           

This approach of treating C<print> and C<printf> like object methods
calls doesn't work for the diamond operator.  That's because it's a
real operator, not just a function with a comma-less argument.  Assuming
you've been storing typeglobs in your structure as we did above, you
can use the built-in function named C<readline> to reads a record just
as C<E<lt>E<gt>> does.  Given the initialization shown above for @fd, this
would work, but only because readline() require a typeglob.  It doesn't
work with objects or strings, which might be a bug we haven't fixed yet.

    $got = readline($fd[0]);

Let it be noted that the flakiness of indirect filehandles is not
related to whether they're strings, typeglobs, objects, or anything else.
It's the syntax of the fundamental operators.  Playing the object
game doesn't help you at all here.

/* 
 * BEGIN EXCERPT FROM PERLFAQ7 
 */

=head2 How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regexp}?

With the exception of regexps, you need to pass references to these
objects.  See L<perlsub/"Pass by Reference"> for this particular
question, and L<perlref> for information on references.

=over 4

=item Passing Variables and Functions

Regular variables and functions are quite easy: just pass in a
reference to an existing or anonymous variable or function:

    func( \$some_scalar );

    func( \$some_array  );
    func( [ 1 .. 10 ]   );

    func( \%some_hash   );
    func( { this => 10, that => 20 }   );

    func( \&some_func   );
    func( sub { $_[0] ** $_[1] }   );

=item Passing Filehandles

To pass filehandles to subroutines, use the C<*FH> or C<\*FH> notations.
These are "typeglobs" - see L<perldata/"Typeglobs and Filehandles">
and especially L<perlsub/"Pass by Reference"> for more information.

Here's an excerpt:

If you're passing around filehandles, you could usually just use the bare
typeglob, like *STDOUT, but typeglobs references would be better because
they'll still work properly under C<use strict 'refs'>.  For example:

    splutter(\*STDOUT);
    sub splutter {
        my $fh = shift;
        print $fh "her um well a hmmm\n";
    }

    $rec = get_rec(\*STDIN);
    sub get_rec {
        my $fh = shift;
        return scalar <$fh>;
    }

If you're planning on generating new filehandles, you could do this:

    sub openit {
        my $name = shift;
        local *FH;
        return open (FH, $path) ? *FH : undef;
    }
    $fh = openit('< /etc/motd');
    print <$fh>;

=item Passing Regexps

To pass regexps around, you'll need to either use one of the highly
experimental regular expression modules from CPAN (Nick Ing-Simmons's
Regexp or Ilya Zakharevich's Devel::Regexp), pass around strings
and use an exception-trapping eval, or else be be very, very clever.
Here's an example of how to pass in a string to be regexp compared:

    sub compare($$) {
        my ($val1, $regexp) = @_;
        my $retval = eval { $val =~ /$regexp/ };
	die if $@;
	return $retval;
    }

    $match = compare("old McDonald", q/d.*D/);

Make sure you never say something like this:

    return eval "\$val =~ /$regexp/";   # WRONG

or someone can sneak shell escapes into the regexp due to the double
interpolation of the eval and the double-quoted string.  For example:

    $pattern_of_evil = 'danger ${ system("rm -rf * &") } danger';

    eval "\$string =~ /$pattern_of_evil/";

Those preferring to be very, very clever might see the O'Reilly book,
I<Mastering Regular Expressions>, by Jeffrey Friedl.  Page 273's
Build_MatchMany_Function() is particularly interesting.  A complete
citation of this book is given in L<perlfaq2>.

=item Passing Methods

To pass an object method into a subroutine, you can do this:

    call_a_lot(10, $some_obj, "methname")
    sub call_a_lot {
        my ($count, $widget, $trick) = @_;
        for (my $i = 0; $i < $count; $i++) {
            $widget->$trick();
        }
    }

Or you can use a closure to bundle up the object and its method call
and arguments:

    my $whatnot =  sub { $some_obj->obfuscate(@args) };
    func($whatnot);
    sub func {
        my $code = shift;
        &$code();
    }

You could also investigate the can() method in the UNIVERSAL class
(part of the standard perl distribution).

=back

/* 
 * BEGIN EXCERPT FROM PERLSUB
 */

If you're passing around filehandles, you could usually just use the bare
typeglob, like C<*STDOUT>, but typeglobs references would be better because
they'll still work properly under S<C<use strict 'refs'>>.  For example:

    splutter(\*STDOUT);
    sub splutter {
	my $fh = shift;
	print $fh "her um well a hmmm\n";
    }

    $rec = get_rec(\*STDIN);
    sub get_rec {
	my $fh = shift;
	return scalar <$fh>;
    }

Another way to do this is using C<*HANDLE{IO}>, see L<perlref> for usage
and caveats.

If you're planning on generating new filehandles, you could do this:

    sub openit {
	my $name = shift;
	local *FH;
	return open (FH, $path) ? *FH : undef;
    }

Although that will actually produce a small memory leak.  See the bottom
of L<perlfunc/open()> for a somewhat cleaner way using the C<IO::Handle>
package.


/* 
 * BEGIN EXCERPT FROM THE FMTEYEWTK ABOUT INDIRECT FILEHANDLES
 */

>From:        Tom Christiansen <tchrist@mox.perl.com>
Subject:      FMTEYEWTK on Indirect Filehandles
Reply-to:     tchrist@mox.perl.com (Tom Christiansen)
Organization: Perl Consulting and Training
Newsgroups:   comp.lang.perl.misc
Date:         12 May 1998

You want to use a filehandle like a normal variable so you can
pass it to or return it from a function, store it in a data
structure, and so on. The solution is to use indirect filehandles
by storing strings, typeglobs, typeglob references, or IO objects
into scalar variables:

    $fh =   SOME_FH;       # bareword is strict-subs hostile
    $fh =  "SOME_FH";      # strict-refs hostile; same package only
    $fh =  *SOME_FH;       # typeglob
    $fh = \*SOME_FH;       # ref to typeglob (bless-able)
    $fh =  *SOME_FH{IO};   # blessed IO::Handle from *SOME_FH typeglob

Or to use the `new' method from the FileHandle or IO modules to
create an anonymous filehandle, store that in a scalar variable,
and use it as though it were a normal filehandle.

    use FileHandle;
    $fh = FileHandle->new();

    use IO::Handle;                     # 5.004 or higher
    $fh = IO::Handle->new();

Then use any of these as you would a normal filehandle.

Here's how this works:

Anywhere that Perl is expecting a filehandle, an indirect
filehandle may be used instead. An indirect filehandle is just a
scalar variable that contains a filehandle. Functions like
`print', `open', `seek', or the functions or the `<FH>' diamond
operator will accept either a read filehandle or a scalar variable
containing one:

    ($ifh, $ofh, $efh) = (*STDIN, *STDOUT, *STDERR);
    print $ofh "Type it: ";
    $got = <$ifh>
    print $efh "What was that: $got";

In the spirit of there being more than one way to do it, here are
seven ways to produce an indirect filehandle. Don't be
intimidated: numbers 3, 6 and 7 are the most common (and 6 and 7
are really the same thing):

1. Barewords
    The first, SOME_FH is rather dubious, because it's not merely a
    string, but a bareword string. It won't be allowed if `use strict
    'subs'' is in effect. Other than that, everything in the next entry
    also applies.

2. Strings
    `"SOME_FH"' is still a string, but at least it's quoted. The big
    problem with this is that it doesn't have package information, so
    if you used it to call a function compiled in a different package,
    that function could get confused unless it were one of the ubiquitous
    handles, like ARGV, STDIN, STDOUT, and STDERR.  You could add the
    package manually, saying perhaps `"main::SOME_FH"'. It won't be
    allowed if `use strict 'refs'' is in effect. The function in question
    can fix it up using the `Symbol::qualify' function, which adds in
    the package. Its cousin, `Symbol::qualify_to_ref', does this and
    produces a reference, silencing the complaints from `strict refs'.

	use Symbol;
	sub function_taking_filehandle_argument {
	    my $fh = shift;
		    # produce typeglob
	    $fh = qualify($fh, scalar caller);          

	# or else this one:

		    # produce typeglob ref
	    $fh = qualify_to_ref($fh, scalar caller);   
	    ...
	}

    The `Symbol::qualify' function produces something useful for
    passing to the `readline' function as described below.

3. Typeglobs
    The `*SOME_FH' notation is a typeglob, an entry in a package
    symbol table. Typeglobs are often nominated as Perl's deepest
    and blackest magic. If you see a star in front of an
    identifier, there are typeglobs involved, and you know you
    have entered a wizardly realm where even gurus fear to tread.

    Unlike the string versions of filehandles shown previously,
    you can do nearly anything with a typeglob you'd like--if not
    a good bit more. They're extremely convenient and useful, once
    you get the hang of them. You don't have to fight with
    packages or any stricture. And although it's not `bless'able
    because it's not a reference, it can be effectively returned
    from functions. A reference to a typeglob can't.

    Here's how typeglobs are typically used for I/O:

	#!/usr/bin/perl
	# demoglob - show how to return local filehandles

	sub ropen {
	    my $path = shift;
	    local *FH;
	    open(FH, $path) || die $!;
	    return *FH;
	}

	$f = ropen("/etc/motd");
	$g = ropen("/etc/termcap");
	print scalar(<$f>), scalar(<$g>);

    >>> Welcome to www.perl.com, the Perl Homepage >>> ########
    TERMINAL TYPE DESCRIPTIONS SOURCE FILE

    If a typeglob is passed in, it can be assigned to a local
    filehandle using a typeglob. After that, normal operations
    like `<>' or any I/O function can be applied to it.

	sub read_N_lines using
	    local *FH = shift;
	    my $count = shift;
	    my @lines = ();
	    while (--$count > 0) {
		push @lines, scalar <FH>;
		last if eof(FH);
	    }
	    return @lines;
	}

	open(TCAP, "/etc/termcap") || die $!;
	@some = read_N_lines(*TCAP, 3);
	print @some;

    >>> ######## TERMINAL TYPE DESCRIPTIONS SOURCE FILE >>> # >>>
    # Version 9.12.0

    It turns out that it also works if the caller forgets to star
    the filehandle or passes it as a string, effectively using
    techniques 1 and 2 from this list. It works only so long as
    they're in the same package as the function in question and
    `strict refs' isn't enabled, though.

	@some = read_N_lines('TCAP', 5);

    That's because assigning a string to a typeglob promotes the
    string to a typeglob of that name, like this:

	*newname = *oldname;        
	*newname = 'oldname';       
		# magically same; promote string to typeglob!

    A careful function would have done either this to qualify its
    filehandle argument:

	use Symbol;
	local *FH = qualify(shift, caller);

    Or prototyped the function to take a typeglob, which
    implicitly does the same thing:

	sub read_N_lines(*$) {
	    # same definition
	}

    Once such a prototype is visible, a call like this:

	@some = read_N_lines(TCAP, 5);

    is really treated as though it were

	@some = &read_N_lines(*TCAP, 5);

4. Typeglob references
    The ` \*SOME_FH' notation produces a reference to a typeglob.
    It can be used to create an object by blessing the reference;
    this is what the FileHandle and IO modules use. Don't try
    passing one of these back from a function, though, because it
    doesn't work. Instead, if you would like an anonymous one of
    these, use the Symbol module.

	use Symbol;
	sub ropen {
	    my $path = shift;
	    my $fh = gensym();
	    open($fh, $path) || die $!;
	    return $fh;
	}

5. IO handles
    The curious `*SOME_FH{IO}' construct is explained in greater
    detail in perlref(1). It accesses the internal IO object
    associated with the handle called SOME_FH. This is a real
    object; it's already blessed even though it's built-in to
    Perl.

	printf "I have %s\n", *STDIN{IO};
    >>> I have IO::Handle=IO(0x80784b8)

    The only issue here is that it can't be used to generate a new
    filehandle the way `Symbol::gensym' can. But if you've already
    accessed the symbol as a filehandle, that's ok. This works
    fine:

	sub ropen {
	    my $path = shift;
	    local *FH;
	    open(FH, $path) || die $!;
	    return *FH{IO};
	}

6. FileHandle
    The standard FileHandle module can be used to create a new filehandle
    to use indirectly. It's just a bit expensive to load; as of the
    5.004 release, merely saying `use FileHandle' loads fifteen text
    files plus several shared libraries, plodding through nearly four
    thousand lines of source code.

	use FileHandle;
	sub ropen {
	    my $path = shift;
	    my $fh = FileHandle->new();
	    open($fh, $path) || die $!;
	    return $fh;
	}

7. IO::Handle
    This is works the same as the FileHandle module, except that
    its name is different. The FileHandle module is really just a
    front-end to this one.  It's still just as crazily expensive.

There's a catch with these indirect filehandles. Only a simple scalar
variable, not part of an array or hash or larger expression, can be
used for things like `print', `printf', or the diamond operator. This
is illegal and won't even compile:

    @fd = (*STDIN, *STDOUT, *STDERR);
    print $fd[1] "Type it: ";                           # WRONG
    $got = <$fd[0]>                                     # WRONG
    print $fd[2] "What was that: $got";                 # WRONG

With `print', you can get around this problem by using a block and
an expression:

    print  { $fd[1] } "funny stuff\n";
    printf { $fd[1] } "Pity the poor %x.\n", 3_735_928_559;
>>> Pity the poor deadbeef.

or even this, which sends the message out to one of two places:

    $ok = -x "/bin/cat";                
    print { $ok ? $fd[1] : $fd[2] } "cat stat $ok\n";
    print { $fd[ 1+ ($ok || 0) ]  } "cat stat $ok\n";           

This kind of thing doesn't work for the diamond operator. In some
cases, though, you may be in luck. The angle bracket notation is
mostly just an interface to the built-in function named
`readline'. You may call it directly--providing that you pass it a
typeglob. Not a string. Not a reference to a typeglob. Just a
typeglob. Given the initialization of @fd above, this would work:

    $got = readline($fd[0]);

But if those had been typeglob references or strings instead of
globs, `readline' wouldn't have worked.

All this monkeying around will probably get to you eventually. If
so, it may well be time to load the FileHandle module (or its
newer alias, IO::Handle), which simplifies much of this. It has a
`new' method to provide an anonymous filehandle, as we saw above.
And it has `print' and `getline' methods (Yes, that's `getline' as
a method, but `readline' when a function. I don't know what I was
thinking when I wrote it.  Is anybody reading this?):

    use FileHandle;
    @fd = ( *STDIN{IO}, *STDOUT{IO}, *STDERR{IO} );
    $fd[1]->print("Type it: ");
    print { $fd[1] } ("Type it: ");      # same, but *much* faster
    $got = $fd[0]->getline();
    $fd[2]->print("What was that: $got");

See also the `open' entry in perlfunc(1) (or Camel:3), FileHandle(3)
(or Camel:7), the perlref(1) manpage's treatment of the so-called
`*foo{THING}' syntax, and the IO modules.
-- 
pos += screamnext[pos]  /* does this goof up anywhere? */
    --Larry Wall, from util.c in the v5.0 perl distribution


------------------------------

Date: 10 Aug 1998 22:25:34 -0400
From: Uri Guttman <uri@sysarch.com>
Subject: Re: What is the purpose of Perl
Message-Id: <x767g05k69.fsf@sysarch.com>

>>>>> "IRAA" == I R A Aggie <fl_aggie@thepentagon.com> writes:

  IRAA> Forgive my presumption here, I only have a vague notion of what
  IRAA> forking does, but wouldn't this give you _parallel_ universes?

  IRAA> James - I don't think the data space is shared...

actually the data and code spaces are shared.

and what definition of universe are you using? if it means the entire
system, then you have to copy the OS, etc., not just fork a process.

you have to do something like (untested :-)

dd if=/dev/kmem of=??

4Q :-)

uri

-- 
Uri Guttman  -----------------  SYStems ARCHitecture and Software Engineering
Perl Hacker for Hire  ----------------------  Perl, Internet, UNIX Consulting
uri@sysarch.com  ------------------------------------  http://www.sysarch.com
The Best Search Engine on the Net -------------  http://www.northernlight.com


------------------------------

Date: 12 Jul 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 Mar 98)
Message-Id: <null>


Administrivia:

Special notice: in a few days, the new group comp.lang.perl.moderated
should be formed. I would rather not support two different groups, and I
know of no other plans to create a digested moderated group. This leaves
me with two options: 1) keep on with this group 2) change to the
moderated one.

If you have opinions on this, send them to
perl-users-request@ruby.oce.orst.edu. 


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 3413
**************************************

home help back first fref pref prev next nref lref last post