Re: r25328 - docs/Perl6/Spec (fwd)
I didn't realise this hadn't gone to the list. Enjoy, all :). -- Forwarded message -- Date: Tue, 17 Feb 2009 14:34:07 +1100 (EST) From: Timothy S. Nelson wayl...@wayland.id.au To: Leon Timmermans faw...@gmail.com Subject: Re: r25328 - docs/Perl6/Spec On Mon, 16 Feb 2009, Leon Timmermans wrote: On Mon, Feb 16, 2009 at 4:50 AM, Timothy S. Nelson wayl...@wayland.id.au wrote: I like it if we can make it work, but it may be too nonsensical to get anything useful out of it. See my discussion below. So far, all ideas based on it result in incredibly verbose code. Creating an IO object should only be one statement. Anything else is failure IMNSHO. I see the problem; lets see if we can address that one too :). First, let me reprint an example I gave below: $socket = new IO::Socket::INET($RemoteHost, $RemotePort, OtherOption = 1); $socket.Blockingness = 1; # Ok, maybe not blockingness, but you know what I mean $socket.OtherOption = 0; # Changed our mind from what we said in the class creation call $socket.open(); # This could be called connect, maybe I wasn't very clear here in what I was trying to demonstrate. This example needed more ... in it. I was assuming that the lines were not all immediately following each other, but I in no way communicated that; sorry :). Allow me to point out that if I wanted to write the first three lines of what I proposed above in a single call, I'd do it like this: $socket = new IO::Socket::INET($RemoteHost, $RemotePort, OtherOption = 0, Blockingness = 1, ); ...which I hope you'll agree is vaguely perlish. Hopefully we can also choose sensible defaults for all these options. My assumption was that people would sometimes want to create an IO object without opening/connecting it, which is why I separated the creation and .open() calls into two separate statements. But choosing sensible defaults applies here; what if we had it open by default on creation unless someone passes in a NoOpen = 1 option? Or maybe leave that to the implementations; files open by default, and sockets don't? This was an example of me not thinking. Basically, it was because it was easier than writing IO::Readable IO::Writeable. I'll ignore the question as it crops up throughout; someone feel free to replace POSIX with something else. Most of them should not be doing defined as implementing both. If a file is opened read-only, the object it returns should not be IO::Writeable. Hence, IO::File and such shouldn't be implementing IO::Readable or IO::Writeable. Such things should remain orthogonal, that is the whole idea of using roles! Ok, I'm vaguely starting to see the purpose of all this :). Say I do this: $fh = new IO::File($filename); while($_ = $fh.getline) { push @lines; } $fh.close(); Yes I know there are better ways to do it, but how does IO::Readable get there? Does it get mixed in at open time or something? As a rakudo user, I'm also wondering whether we shouldn't be referring more to the Parrot IO stuff, but that may just be me. Parrot has very different goals for its IO interface: being able to implement the IO of all implemented languages is more important than having the best possible interface. In short, it's an implementation detail. Sorry, I wasn't clear again. I was thinking more from the point of view that a number of the things we've said appear to refer to the underlying OS calls and how they map to Perl6. I was thinking maybe we should talk about how the Parrot calls map to Perl6 (in our discussion, not in the Spec). But Maybe they're similar enough anyway that it doesn't really matter :). Question -- is there a reason this is in IO, instead of eg. S29? If not, I'll move it there. AFAIK it's mostly used for obscure IO calls. I do agree it shouldn't really be in S16 though. Ok, I've moved it. Disagree -- I think these belong in IO::Unbuffered. Maybe we could make that optional, though :). It may have a purpose in IO::POSIX, but other than that it doesn't make too much sense to me. The interface is stuck in 1969. We should make our open flexible enough that it can handle the use cases that now require sysopen, without having the same sucky interface. Sorry, I was unclear. I don't think those calls belong in IO::Unbuffered, but that whatever does our open should, if the object does IO::Unbuffered, apply the correct parameters. But I agree with you about unification of interface. Hmm. I still haven't gotten the hang of Perl 6. What I want is for the name of this function to be the one that automatically gets called on object creation. Then you do something like this: $fobj = new IO::File($filename); # Creates handle $fobj.open(); # opens file Opening a file shouldn't be two lines, this is Perl! I think this whole Openable thing is harming us. Simple things should be simple. I agree
Re: The use of roles in S16 (Was: Re: r25328 - docs/Perl6/Spec)
Daniel Ruoso wrote: Maybe I'm thinking sideways again, but I haven't thought of open as being a method of any IO object, because usually open is the thing that gets you an IO Object. I'd expect the plain open to be really a sub (maybe a is export method in the generic IO role), that does whatever it needs to do to provide you an IO object, including composing the roles according to the features it supports. An important concept of testability is to decouple the use of objects from their creation. Global factory functions make testing harder. That said, in perl we can always override them, which would provide the necessary seam. One way of thinking about open is that it is a method on a file system object (or, more generally, on an IO server role): $fh = $*os.open($filename, :rw); $fh = $internet.open($url, :ro); ... Admittedly, that approach would tend to lead Perl down the road of Java, so it's probably good to have a global sub to hide the underlying details. It might seem even better be to introduce an object that represents the concept of an openable thing: $file = $file_system.find($filename); $fh = $file.open(:rw); However, file systems are very OS-dependent, so it is generally counterproductive to attempt to build a data structure that shadows a filesystem (e.g. what happens to $file if the underlying file is renamed?)
Re: The use of roles in S16 (Was: Re: r25328 - docs/Perl6/Spec)
On 2009 Feb 16, at 22:44, Timothy S. Nelson wrote: So you can have a stream handle which does IO::Writeable, but will throw an error on any attempt to write? Anyway, you've answered my question in the other e-mail. Not sure what you're getting at, but the obvious example is a writeable handle on a full filesystem. I don't think we want Perl deciding to remove IO::Writeable because the fs happens to be full at the instant it's opened. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon universityKF8NH PGP.sig Description: This is a digitally signed message part
The use of roles in S16 (Was: Re: r25328 - docs/Perl6/Spec)
Em Sáb, 2009-02-14 às 18:01 +0100, Leon Timmermans escreveu: On Sat, Feb 14, 2009 at 6:38 AM, pugs-comm...@feather.perl6.nl wrote: +=head2 IO::Openable +This role implies that the object can be connected to, or listened on. I'm not sure if I really hate or love this. I'm not quite convinced if the use of it anyway. Maybe I'm thinking sideways again, but I haven't thought of open as being a method of any IO object, because usually open is the thing that gets you an IO Object. I'd expect the plain open to be really a sub (maybe a is export method in the generic IO role), that does whatever it needs to do to provide you an IO object, including composing the roles according to the features it supports. One important thing here, is that the roles are not intended to represent attributes of the object. For instance, IO::Readable and IO::Writeable are not going to be composed depending on the parameters you send to open, but if you're in a Linux system, it should probably return an object that does IO::Linux26 (which does IO::POSIX[$SomeLevel] does IO::BSD[$Somewhat], which should also compose IO::Readable and IO::Writeable independent of the open mode). So the idea is not about having the object to have the roles dinamically composed and de-composed depending on the access mode, but to have a way to implement a custom IO object that performs only the features it want to implement and yet being able to be used interchangeably with other IO objects. That way, in the code that uses an IO object, if you want to be able to do unbuffered raw read from the object you receive as argument, you use sub foo(IO::Readable $bar) {...} and that way, it should be easy to provide a entirely made-up IO object that can be used by foo without any harm or magic. daniel
Re: The use of roles in S16 (Was: Re: r25328 - docs/Perl6/Spec)
On Mon, 16 Feb 2009, Daniel Ruoso wrote: Em Sáb, 2009-02-14 às 18:01 +0100, Leon Timmermans escreveu: On Sat, Feb 14, 2009 at 6:38 AM, pugs-comm...@feather.perl6.nl wrote: +=head2 IO::Openable +This role implies that the object can be connected to, or listened on. I'm not sure if I really hate or love this. I'm not quite convinced if the use of it anyway. Maybe I'm thinking sideways again, but I haven't thought of open as being a method of any IO object, because usually open is the thing that gets you an IO Object. [See my other e-mail to Leon for my comments on this]. One important thing here, is that the roles are not intended to represent attributes of the object. For instance, IO::Readable and IO::Writeable are not going to be composed depending on the parameters you send to open, but if you're in a Linux system, it should probably return an object that does IO::Linux26 (which does IO::POSIX[$SomeLevel] does IO::BSD[$Somewhat], which should also compose IO::Readable and IO::Writeable independent of the open mode). So you can have a stream handle which does IO::Writeable, but will throw an error on any attempt to write? Anyway, you've answered my question in the other e-mail. Thyanks, - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+++ PGP-+++ R(+) !tv b++ DI D G+ e++ h! y- -END GEEK CODE BLOCK-
Re: r25328 - docs/Perl6/Spec
On Sat, 14 Feb 2009, Leon Timmermans wrote: On Sat, Feb 14, 2009 at 6:38 AM, pugs-comm...@feather.perl6.nl wrote: +=head2 IO::Openable + +This role implies that the object can be connected to, or listened on. + +=over 4 + +=item open + + method Bool open(); + +Attempts to open the handle. Depending on the implementation, this could be an open() +call, a connect(), a listen(), or something similar. + +=back + I'm not sure if I really hate or love this. I'm not quite convinced if the use of it anyway. I like it if we can make it work, but it may be too nonsensical to get anything useful out of it. See my discussion below. Why should this do POSIX? What about non-POSIX operating systems? This was an example of me not thinking. Basically, it was because it was easier than writing IO::Readable IO::Writeable. I'll ignore the question as it crops up throughout; someone feel free to replace POSIX with something else. I haven't written a program that was intended to be run on anything other than Unix or Embedded in years, so I'm quite pleased to get some input from non-POSIX types. I'm happy (once we sort out what we're doing) for others to edit the thing, now that I've gone and restructured it all :). As a rakudo user, I'm also wondering whether we shouldn't be referring more to the Parrot IO stuff, but that may just be me. http://www.parrotcode.org/docs/ops/io.html +=item syscall + That functions should be well hidden Question -- is there a reason this is in IO, instead of eg. S29? If not, I'll move it there. +=item sysopen + I vote for sysopen (and all other sys functions) to be wiped out of existence. Disagree -- I think these belong in IO::Unbuffered. Maybe we could make that optional, though :). +=head1 Classes + +=head2 IO::File + +This does file input and output. + +class IO::File does IO::POSIX does IO::Closeable does IO::Openable { +... +} + +=over + +=item init + + method init(String $filename, $options?); + method init(Int $fd); + + # Read + $fobj = new IO::File($filename); + + # Write + $fobj = new IO::File($filename, :w); + + # Read using file descriptor + $fobj = new IO::File($fd); + +Associate an IO object with an already-open file descriptor, +presumably passed in from the parent process. + +=back Why is that function called init, and not open? That's rather non-intuitive. Hmm. I still haven't gotten the hang of Perl 6. What I want is for the name of this function to be the one that automatically gets called on object creation. Then you do something like this: $fobj = new IO::File($filename); # Creates handle $fobj.open(); # opens file This should do IO::Seekable and (to be written) IO::Stattable. Should it? I'm just thinking about the interactions between IO::File and IO::FileSystem. Maybe I'm just wondering about the name :). I'd argue that maybe class IO::File ... { has IO::FileSystemEntry $FSEntry; ... } ...and that you could then do: $fobj = new IO::File($filename); if($fobj.FSEntry.ModificationTime '2008') { print Modified this year\n; } $fobj.open() ... In other words, I'm arguing that maybe we need a separate class for the calls that do stuff to the outside of a file, verses the calls that do stuff to the inside of a file. But maybe that's what roles are for. I'm undecided. Thoughts, anyone? +=head2 IO::Socket::INET + +class IO::Socket::INET does IO::Socket { +... +} + +=over + +=item init + + method Bool init($RemoteHost, $RemotePort, $LocalHost?, $LocalPort?); + +=item open($Listen?); + +If $Listen is 0, it does a connect(). If $Listen is 1, it does a connect() and a +listen(). If $Listen is 2, it does a listen(), but no connect(). + I *really* hate that interface, and I don't see how it covers an accepting socket. Ok, I agree there's room for improvement, but I'm not 100% sure I agree on the details. IMO there should be two calls At least 3 :). method IO connect($RemoteHost, $RemotePort, *%options) where *%options can contain things like the local address, non-blockingness, etc... I'd break this into two; one like the init call above that creates the object, and has the local and remote host/port passed in, but doesn't do any calls. Maybe something like this example for a client: $socket = new IO::Socket::INET($RemoteHost, $RemotePort, OtherOption = 1); $socket.Blockingness = 1; # Ok, maybe not blockingness, but you know what I mean $socket.OtherOption = 0; # Changed our mind from what we said in the class creation call $socket.open(); # This could be called connect, maybe I'm kinda keen to call the function open() instead of connect(), so that things are more consistent across the whole IO interface, but I agree that attaching the listen stuff to that call was a bad idea. For the server, I'd suggest an additional role, IO::Listening, that has both listen() and accept() calls on it. Would that work for you? Or is
Re: r25328 - docs/Perl6/Spec
On 2009 Feb 15, at 22:50, Timothy S. Nelson wrote: On Sat, 14 Feb 2009, Leon Timmermans wrote: +=item sysopen I vote for sysopen (and all other sys functions) to be wiped out of existence. Disagree -- I think these belong in IO::Unbuffered. Maybe we could make that optional, though I think sysopen etc. should go away, instead allowing open() to specify unbuffered. In general anything that exposes a system file descriptor is an abstraction violation (unless in a module which is intended to do so; IO::Posix?). The original intent behind sysopen() was to allow system file descriptor mode flags to be used; this was a workaround for perl5's open being insufficiently flexible. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon universityKF8NH PGP.sig Description: This is a digitally signed message part
Re: r25328 - docs/Perl6/Spec
On Sun, 15 Feb 2009, Brandon S. Allbery KF8NH wrote: On 2009 Feb 15, at 22:50, Timothy S. Nelson wrote: On Sat, 14 Feb 2009, Leon Timmermans wrote: +=item sysopen I vote for sysopen (and all other sys functions) to be wiped out of existence. Disagree -- I think these belong in IO::Unbuffered. Maybe we could make that optional, though I think sysopen etc. should go away, instead allowing open() to specify unbuffered. In general anything that exposes a system file descriptor is an abstraction violation (unless in a module which is intended to do so; IO::Posix?). I'm not convinced about it being an option to open, but if you said instead that it should be an attribute on a role (IO::Openable?), then I'd happily agree. The original intent behind sysopen() was to allow system file descriptor mode flags to be used; this was a workaround for perl5's open being insufficiently flexible. That's good to know; thanks. :) - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+++ PGP-+++ R(+) !tv b++ DI D G+ e++ h! y- -END GEEK CODE BLOCK-
Re: r25328 - docs/Perl6/Spec
On Sat, Feb 14, 2009 at 6:38 AM, pugs-comm...@feather.perl6.nl wrote: +=head2 IO::Openable + +This role implies that the object can be connected to, or listened on. + +=over 4 + +=item open + + method Bool open(); + +Attempts to open the handle. Depending on the implementation, this could be an open() +call, a connect(), a listen(), or something similar. + +=back + I'm not sure if I really hate or love this. I'm not quite convinced if the use of it anyway. +=head2 IO::Socket + +role IO::Socket does IO::POSIX does IO::Openable does IO::Closeable { +... +} + +=over + +=item IO.accept + +=item IO.bind + +=item Socket.pair + +our List of IO method pair(Int $domain, Int $type, Int $protocol) + +A wrapper for socketpair(2), returns a pair of IO objects representing the +reader and writer ends of the socket. + + use Socket; + ($r, $w) = Socket.pair(AF_UNIX, SOCK_STREAM, PF_UNSPEC); + + +=back + Why should this do POSIX? What about non-POSIX operating systems? +=item syscall + That functions should be well hidden +=item sysopen + I vote for sysopen (and all other sys functions) to be wiped out of existence. +=head1 Classes + +=head2 IO::File + +This does file input and output. + +class IO::File does IO::POSIX does IO::Closeable does IO::Openable { +... +} + +=over + +=item init + + method init(String $filename, $options?); + method init(Int $fd); + + # Read + $fobj = new IO::File($filename); + + # Write + $fobj = new IO::File($filename, :w); + + # Read using file descriptor + $fobj = new IO::File($fd); + +Associate an IO object with an already-open file descriptor, +presumably passed in from the parent process. + +=back Why should this do POSIX? What about non-POSIX operating systems? Why is that function called init, and not open? That's rather non-intuitive. This should do IO::Seekable and (to be written) IO::Stattable. +=head2 IO::FileSystem + +This reads directories, worries about ownership and permissions, and the like. + +class IO::FileSystem does IO::POSIX does IO::Closeable does IO::Openable { +... +} Why should this do POSIX? What about non-POSIX operating systems? +=head2 IO::Socket::INET + +class IO::Socket::INET does IO::Socket { +... +} + +=over + +=item init + + method Bool init($RemoteHost, $RemotePort, $LocalHost?, $LocalPort?); + +=item open($Listen?); + +If $Listen is 0, it does a connect(). If $Listen is 1, it does a connect() and a +listen(). If $Listen is 2, it does a listen(), but no connect(). + I *really* hate that interface, and I don't see how it covers an accepting socket. IMO there should be two calls method IO connect($RemoteHost, $RemotePort, *%options) where *%options can contain things like the local address, non-blockingness, etc... method IO::Accepting listen($LocalHost, $LocalPort, *%options) role IO::Accepting does IO::Socket { IO accept(); } -=head1 Input and Output +=head2 IO::Pipe -=over 4 +class IO::Pipe does IO::POSIX does IO::Closeable does IO::Openable { +... +} Why should this do POSIX? What about non-POSIX operating systems? Regards, Leon Timmermans
Re: r25328 - docs/Perl6/Spec
On 2009 Feb 14, at 12:01, Leon Timmermans wrote an unending refrain of: Why should this do POSIX? What about non-POSIX operating systems? I think the point here is that on POSIX systems that gets you ioctl() and fcntl(), and on non-POSIX systems either they don't exist or they throw runtime errors. Aside from my earlier suggestion that non-POSIX systems generally have similar functions for which we should consider a common rubric, I'm not sure if this (does IO::POSIX) is backwards or if my/our(?) understanding of does is backwards, or possibly tangential. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon universityKF8NH PGP.sig Description: This is a digitally signed message part
Re: r25328 - docs/Perl6/Spec
On Sat, Feb 14, 2009 at 10:31 PM, Brandon S. Allbery KF8NH allb...@ece.cmu.edu wrote: I think the point here is that on POSIX systems that gets you ioctl() and fcntl(), and on non-POSIX systems either they don't exist or they throw runtime errors. Aside from my earlier suggestion that non-POSIX systems generally have similar functions for which we should consider a common rubric, I'm not sure if this (does IO::POSIX) is backwards or if my/our(?) understanding of does is backwards, or possibly tangential. IMO IO::POSIX should do exactly what it says it does: implement POSIX as closely as possible. Since we probably can't implement much of it on non-POSIX platforms, I don't think it should be part of our specification (though I do think it should be part of our implementation, because it is definitely useful). I think it would be a lot better to implement a more portable wrapper around the necessary functionality. Regards, Leon
r25328 - docs/Perl6/Spec
Author: wayland Date: 2009-02-14 06:38:34 +0100 (Sat, 14 Feb 2009) New Revision: 25328 Modified: docs/Perl6/Spec/S16-io.pod Log: S16-io: Reorganised everything, grouping things together a bit better. This is only a draft; otherwise I'd be a lot more careful :). Specifically, I've: - Taken some of the stuff that was spread throughout the document, and put it in with its associated role - Created sections for a lot of the different classes we'll need It still needs a lot of work. Modified: docs/Perl6/Spec/S16-io.pod === --- docs/Perl6/Spec/S16-io.pod 2009-02-14 05:28:12 UTC (rev 25327) +++ docs/Perl6/Spec/S16-io.pod 2009-02-14 05:38:34 UTC (rev 25328) @@ -82,8 +82,17 @@ =item method Bool close() -returns True on success, but might return an unthrown failure. +Closes the file or pipe associated with the object. +Returns True on success, but might return an unthrown failure. +Returns true only if IO buffers are successfully flushed and closes the system +file descriptor. + +You don't have to close IO if you are immediately going to do +another Copen on it, because Copen will close it for you. (See +Copen.) However, an explicit Cclose on an input file resets the line +counter (C$.), while the implicit close done by Copen does not. + =back =head2 IO::Buffered @@ -184,6 +193,15 @@ Reads the next character in the set $.encoding according to the $.locale. +=item getc + +our Bool method getc (IO $self: Bool :async) + +Returns the next character from the input stream attached to IO, +or the undefined value at end of file, or if there was an error (in +the latter case C$! is set). The C:async flag lets the call +return an undefined value if no character is immediately available. + =cut =head2 IO::Writeable::Encoded @@ -218,12 +236,165 @@ $.output_field_seaparator and $.output_escape is set, it should do the escaping. +=item print + +our Bool method print (IO $self: *...@list) +our Bool multi print (*...@list) +our Bool method print (Str $self: IO $io) + +Prints a string or a list of strings. Returns Bool::True if +successful, Failure otherwise. The IO handle, if supplied, must be +an object that supports I/O. Indirect objects in Perl 6 must always +be followed by a colon, and any indirect object more complicated than +a variable should be put into parentheses. + +If IO is omitted, prints to C$*DEFOUT, which is aliased to C$*OUT +when the program starts but may be temporarily or permanently rebound to +some other file handle. The form with leading dot prints C$_ to C$*DEFOUT +unless an explicit filehandle is supplied. + +It is a compiler error to use a bare Cprint without arguments. +(However, it's fine if you have an explicit argument list that evaluates to +the empty list at runtime.) + +There is are no variables corresponding to Perl 5's C$, and +C$\ variables. Use Cjoin to interpose separators; use filehandle +properties to change line endings. + +=item say + +our Bool method say (IO $self: *...@list) +our Bool multi say (*...@list) +our Bool method say (Str $self: IO $io) + +This is identical to print() except that it auto-appends a newline after +the final argument. + +Was:print Hello, world!\n; +Now:say Hello, world!; + +As with Cprint, it is a compiler error to use a bare Csay without +arguments. + +=item printf + +our Bool method printf (IO $self: Str $fmt, *...@list) +our Bool multi printf (Str $fmt, *...@list) + +The function form works as in Perl 5 and always prints to $*DEFOUT. +The method form uses IO handles, not formats, as objects. + =back +=head2 IO::Openable + +This role implies that the object can be connected to, or listened on. + +=over 4 + +=item open + + method Bool open(); + +Attempts to open the handle. Depending on the implementation, this could be an open() +call, a connect(), a listen(), or something similar. + +=back + +=head2 IO::Socket + +role IO::Socket does IO::POSIX does IO::Openable does IO::Closeable { +... +} + +=over + +=item IO.accept + +=item IO.bind + +=item Socket.pair + +our List of IO method pair(Int $domain, Int $type, Int $protocol) + +A wrapper for socketpair(2), returns a pair of IO objects representing the +reader and writer ends of the socket. + + use Socket; + ($r, $w) = Socket.pair(AF_UNIX, SOCK_STREAM, PF_UNSPEC); + + +=back + =head1 Filehandles, files, and directories =over 4 +=item IO.fcntl + +Available only as a handle method. + +=item IO.ioctl + +Available only as a handle method. + +=item IO.name + +The C.name method returns the name of the file/socket/uri the handle +was opened with, if known. Returns undef otherwise. There is no +corresponding Cname() function. + +=item syscall + +=item sysopen + +=item umask + +=item utime + +=back + +=head1 Classes + +=head2 IO::File + +This does file input and output. + +class IO::File does IO::POSIX