RFC 129 (v1) Replace default filehandle/select with $DEFOUT, $DEFERR, $DEFIN

[email protected] (Perl6 RFC Librarian)
Newsgroups perl.perl6.language.io,perl.perl6.announce
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.