This and other RFCs are available on the web at
  http://dev.perl.org/rfc/

=head1 TITLE

Replace default filehandle/select with $DEFOUT, $DEFERR, $DEFIN

=head1 VERSION

   Maintainer: Nathan Wiger <[EMAIL PROTECTED]>
   Date: 17 Aug 2000
   Version: 1
   Mailing List: [EMAIL PROTECTED]
   Number: 129
   Status: Developing

=head1 ABSTRACT

The concept of a "default filehandle" is nebulous. Many users
can't get their heads around it, and even if they can, it is
still kind of mysterious.

This proposes that the "default filehandle" and 2-arg select
be dropped from Perl 6 and replaced with the variable C<$DEFOUT>,
the Default Output handle. Whatever this variable contains will
be what is printed to by default. This will make default output
be consistent with the C<fileobject> approach and also other
Perl vars.

In addition, this RFC proposes two new variables, C<$DEFERR>
and C<$DEFIN>, the Default Error and Default Input handles.
These can be used to redirect default error output and default
input, for added flexibility.

=head1 DESCRIPTION

=head2 $DEFOUT

Currently, the "default filehandle" ("DF" to save typing) is
hidden. It can only be accessed or changed via the C<select>
function. 

With the advent of full-featured C<fileobjects>, having a
special DF is unnecessary. Instead, we simply make a variable,
called C<$DEFOUT>, which is where unspecified output is sent.

Below are some examples of Perl 5 versus Perl 6 syntax:

   P5                        P6 
   -----------------------   -----------------------
   select FILE;              $DEFOUT = $fileobject;
   
   $oldh = select;           $oldh = $DEFOUT;

   $oldh = select FILE;      $oldh = $DEFOUT;
                             $DEFOUT = $fileobject;

   $| = 1                    $DEFOUT->autoflush(1);


What advantages besides a new syntax are there? Several:

   1. The rule is easier. No DF, just "everything goes
      to $DEFOUT by default". Changing this is done by
      simple assignment.

   2. It's less hidden. Most everything else in Perl is
      handled in variables such as @INC, %ENV, and so
      forth. This makes filehandles that much easier.

   3. Access to object methods is available directly on
      the current filehandle object via $DEFOUT->method,
      eliminating the need for $|, $/, $\, and so on.[1]

   4. No more 2-arg select vs. 4-arg select confusion.

Whatever object C<$DEFOUT> contains is what default output
goes to and what the object methods work on. There is no
mysterious hidden DF. C<$DEFOUT> works just like other 
variables.

=head2 $DEFERR

The new C<$DEFERR> variable can be used to easily redirect
error output as well, something you often want to do if
you're not attached to a tty. However, having a script that
runs easily in both environments is tricky in Perl 5:

   if ( $have_a_tty ) {
      print STDERR "Warning: Bad stuff\n";
   } else {
      print ERRORLOG "Warning: Bad stuff\n";
   }

You have to put checks similar to this for many functions
and different situations. Plus, it doesn't catch C<carp> or
C<die> calls embedded in modules, meaning that you will
always lose some important error output.

With C<$DEFERR>, all error functions are set to act on it
instead of C<$STDERR> by default. So, the Perl 6 version
of the above is replaced by a single, simple line of code
at the top of your main program:

   $DEFERR = $ERRORLOG unless $have_a_tty;

Presto, all error-related functions now redirect to your
error log automatically. All through simple assignment.

Plus, if you have functions that you want to explicitly
print to C<$STDERR> you can still do so, another benefit:

   warn "Badness!";          # goes to $DEFERR
   print $STDERR "Badness!"  # explicitly to $STDERR

This is not possible in Perl 5.[2]

=head2 $DEFIN

The new C<$DEFIN> accomplishes a similar thing, but with 
input. Currently, the special <> filehandle acts on one of
two things, either C<@ARGV> or <STDIN> (if C<@ARGV> is
empty).

With C<$DEFIN>, the sequence is instead C<@ARGV> or
C<$DEFIN>. This adds valuable functionality:

   # Figure out our input source based on what's open
   $DEFIN = $infile || $instream || $STDIN;
   @data = <>;

This allows valuable compartmentalization of code. The 
simple <> construct is now a synonym for C<$DEFIN>. This
means that you can place something like the C<@data = <>>
line in a module, and allow the top-level code to change
the data source based on a simple assignment. You no
longer have to pass filehandles into functions or do
complex C<tie> manuevers to gain this ability.

Plus, with C<$DEFIN>, if you have a routine that must
read from C<$STDIN>, you can still do so easily by 
explicitly saying:

   $yes_or_no = <$STDIN>;   # explicitly from $STDIN
   @data = <>;              # read from $DEFIN

=head2 Naming

The naming of the variables was chosen to make them
consistent with the Standard IO handles C<$STDIN>,
C<$STDOUT>, and C<$STDERR>.

=head1 IMPLEMENTATION

Remove 2-arg C<select>. Make sure p52p6 translates C<select>
to the new syntax.

Create C<$DEFOUT> variable and reset output functions to act
on C<$DEFOUT> instead of the default filehandle.

Add C<$DEFERR> variable and reset error functions (such as
warn and die) to print to C<$DEFERR> instead of C<$STDERR>.

Add C<$DEFIN> and reset <> and other default input to work
on C<$DEFIN> instead of C<$STDIN>.

=head1 NOTES

[1] This RFC does not take a firm stance on eliminating
$|, $/, $\, and friends. However, this approach to handling
default input and output does mean they are no longer needed.
I do think they should go, but this RFC does not require it.

[2] Disclaimer: To my knowledge. But I'm pretty sure.

=head1 REFERENCES

RFC 14: Modify open() to support FileObjects and Extensibility

RFC 30: STDIN, STDOUT, and STDERR should be renamed

Reply via email to