On Sun, 29 Oct 1995, Charles Bailey wrote:
> [. Sorry to come late to the discussion; I've just got back into town after
> several days away, and am *way* behind on p5p - CB ]
No problem.
> Kenneth Albanowski writes:
> | 1. Can we currently use blessed FileHandle objects everywhere bearword
> | handles are accessible?
>
> I think so, though I haven't tested it extensively.
This has been hashed over a bit, and yes, most operators can handle it
(sorry, no pun intended it.
> | 2. Is it possible to write a class, IO::Handle, that can accept a wide
> | range of constructors (as discussed) and return appropriate blessed
> | objects of FileHandle decent? Who feels like writing this, if it hasn't
> | already been written? Next goal: extend to have logical methods, so
> | $fh->close() works, as does open(), print(), etc.
>
> The basic ability is already there in the last set of patches, isn't it?
> This class should do nothing except create the blessed reference.
Hmm. Well, this is where it gets complex, due to class heirarchies and
such. Yes, some bits are there, but even in Chip's patch, it's hard to
see them for POSIX. If I get the time, I intend to at least rough out a
complete set of IO:: modules, FileHandle support and all.
> No. It could be added pretty easily, either by keeping anonymous typeglobs and
> creating a convention for storing data in other slots, or by using unused
> members of a SVt_PVIO as a way to attach additional data.
Hash slots of anonymous typeglobs seems to be the best solution all
around. This however means that raw FileHandles, using "bearword" syntax
as they do, can't participate in this. The hash slot of "STDIN" is
%STDIN. This isn't particularly good.
I suppose we could move to additional members (perhaps even an HV*) in the
PVIO, but it seems that user-level code can do everything we want for now.
> | 5. Is it possible to override open() in such a way that this syntax is
> | possible, and compatible with normal operations and method calls?
>
> No. CORE::open (in fact, all the core file I/O routines) know about SVt_PVIOs.
> At the moment, we don't have a way to specify this type from Perl, and we don't
> have a replacement notion. Candidates discussed thus far include:
> - an I/O type (whether ^fh or $fh = anonymous(IO)): type-checking in CORE
> and user routines is direct; derived classes must create a reference
> to an I/O-type object, or tie an object to an I/O type
> - FileHandle class: type-checking in CORE and user routines is direct, but
> derived classes are not possible
> - class ISA FileHandle: type-checking in CORE and user routines is
> indirect and quite expensive; derived classes can create any type of
> reference they want, as long as the class into which it is blessed
> ISA FileHandle
> - don't bother: any object can be used for I/O; if it doesn't contain
> a file descriptor in the right place, just return a runtime error
Current thoughts on this involve using prototypes to let Perl
automatically convert this:
foo(FH,"abc");
into this:
foo(\*FH,"abc");
If I can talk Larry into providing multiple prototype for a single
function, then all the variants of CORE::open() could be directly supported.
As for FileHandle semantics, my proferred opinion is that the mechanism
you describe as "class ISA FileHandle" should be used -- anything that
ISA FileHandle (directly or indirectly) is usable as such.
Currently the built in IO functions seem to use something remeniscent of
"don't bother", and therefor I like "class ISA FileHandle" because it's
directly compatible, and is nicely OO.
This does however miss the point that FileHandles are real internal types
(PVIO). Unfortunately, Perl's OO doesn't line up with it's typing system,
so it's unclear what a "unified" solution would look like.
I am strongly _against_ ^FH notation, and would prefer FileHandles to be
more OO, not less OO.
> | $fh = open("<foo");
> | #same as $fh = new FileHandle;open($fh,"<foo");
>
> Both are possible now; neither is equivalent to C<open(FH,'foo')>.
Decidedly.
> | 6. What is the _simplest_ way to get tie() functionallity working on
> | filehandles, that requires the fewest changes to perlCORE?
>
> Hmm. How's this for a general description:
> Decide on a way to identify an I/O handle, so we can tie to one. Add check for
> package methods to CORE routines for <>, binmode, chmod, chown, close, fcntl,
> file tests (stat), flock, getc, open (? - only if we allow ties by name),
> print, printf, read, rename, seek, sysread, syswrite, tell, unlink, and write.
> Socket methods are also a possibility. Other file-associated CORE routines
> operate on names, except C<select>, which is so bound to C-style file
> descriptors that I'm not sure whether or how it'd interact with tied objects.
> Write a base package which supplies default methods, often in terms of other
> methods, or just fatal stubs.
My stated opinion on _this_ one is that tie() really shouldn't apply to
FileHandles, and instead should be implicit: any object that ISA
FileHandle will have methods named like "PRINT", "READ", and "TELL"
invoked at the right times.
Once again, this is more OO and less "internal". If filehandles were
given explicit names (^FH) then obviously a tie() style interface becomes
possible.
> | 7. Are there any other questions?
>
> 7.1 How do we identify an I/O value?
Right now, I'm all for ignoring this one, and letting the OO method call
syntax work out the details. (As per above.)
> 7.2 How do we alias an I/O value into a typeglob (pretty much falls out of the
> answer to 7.1)?
You mean put the PVIO part of a glob into an anonymous glob, without
transferring the rest? Interesting idea. One of Larry's comments about a
new "glob notation" seems appropriate here. Something like this:
*a{filehandle} = *STDIN{filehandle};
(Or something like that. Ideally, you get to use keys(), and in general
treat a glob just like a hash. The fallout with regards to regularlizing
access to symbol tables should be obvious.)
> 7.3 Do we set up a mechanism to tie IO handles, or do we just use ISA
> FileHandle?
As above, I'm for ISA FileHandle.
Actually, in writing this, I have realized that I really _am_ for more OO
stuff, and less "interalized types", which I never stated clearly before.
Hmm. For those that have read down this far, here's a question for you:
If Perl got compiled regexps, what sort of object would you like to see
them as? Entries into the symbol table (and thus with their own symbol
like "$" or "@"), or as references to a Regexp object?
If the former, then one might have code like this:
~a = /\S+/c; # ~a is the variable, /c means compile
if( /~a/ ) {
#...
}
If the latter:
$a = /\S+/c;
if( /$a/ ) {
#...
}
To round this out, what if we wanted to add "tie" functionality? In the
former, this might be:
tie(~a,MyRegexpType,...);
s/~a/abc/; #invokes MyRegexpType::SUBST(~a,"abc",\$_);
In the latter, the only suggestion I have is the same suggestion I have
for filehandles:
package Regexp;
sub SUBST {
my($regexpref,$replacement,$textref) = @_;
#...
}
sub MATCH { ... }
This however leads to exactly the same problem as with filehandles: you
can only "tie" the entire class of Regexp objects, or by inheritance,
particular objects _at creation_, and if you can't override creation,
then you can't change the class. Hence, this code:
$a = /\S+/c;
Is fated to _always_ producing an object of type "Regexp", and there is
no way of changing it (later on) to an object of type "MyRegexp" (which
ISA Regexp) so that it gets the new behavior. We'd have to say something
like this:
$a = new MyRegexp '\S+';
With named objects, and a real tie(), we can change the behaviour of
objects _after_ creation, and during there lifespan.
Next question: is such behaviour a good idea? For hashes, the answer seems
to be "yes", because that way you can attach, disconnect, and reconnect
hashs from various databases completely behind the back of some code.
For FileHandles, since the handle is referring to some outside unit
(perhaps a disk file, or a pipe, or a socket) it seems pretty clear that
changing behaviour (or at least changing tie()'s) in mid-steam is _not_
what we want. Or am I wrong here? What if the tie() was simply to install
a "tee connection" into the filehandle, so a debugging trace could be
made?
For Regexps, I have absolutely no idea how this would even be used in the
first place, so I can't offer much comment.
Thoughts?
> Regards,
> Charles Bailey bailey@genetics.upenn.edu
>
--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)