Mailing List Archive

FileHandle RFD (was Re: "Line Noise" considered offensive)
[.I'm hereby summarizing and pulling together my comments on FileHandle
stuff. I've decided that things are just to splintered right now to make
writing large chunks of code (IO::Handle, etc.) a good proposition.

This forms a Request For Discussion, a stopping point for me, until the
issue reaches some form of resolution. I realize that Perl 6 might be that
resolution. :-)]

I'm rapidly getting to be of two minds on this subject: the I/O "SFIO
discipline" style, where behaviours can be stacked onto a handle, has
efficiency and simplicity going for it. The OO approach might be more
flexible.

The problem, as I see it, is that Perl will definitely need to support the
following techniques at some point in the future:

1. A "tied" file handle, without a real underlying handle:

OpenCurses(FH);
print FH "Abc";
ioctl FH, ATTRON, "bold"; # For lack of a better OOB call
close FH;

2. A tied handle with behaviour added to the standard set:

UUOpen(FH,">>foo.uue");
print FH "Now is the time...\n";
close FH;

If we go the OO route, then these will also need to be supported:

3. Provide custom "methods", and allow capture of standard methods:

SomeOOOpen(FH,">foo");
print FH "abc";
boogle FH 12;
gentlyclose FH;

4. Allow OO calling notation:

$a = new SomeOO ">foo";
$a->print("abc");
$a->boogle(12);
$a->gentlyclose();

Considering that Perl already has the "FileHandle" class, and lets
instances of that class (or a derivative) be used as in #4, this seems to
be a count in favour of OO. But #3 isn't implemented right now, nor is #1
or #2.

So... Which of #1, #2, or #3 does someone want to implement first? #2
seems to consist of very minor changes to the core, perhaps as part of
installing SFIO. Specifically, each call to file I/O functions would need
to check for some "tied" marker, and arrange for the callback (perhaps a
method in a package) to be called.

#1 is a bit more complex then #2, as no underlying file handle exists. One
could always open ">/dev/null", but is this the right approach? This
style is rather similar to the current tie() approach.

#3 is a completely different set of work, and probably least efficient.
It is the most flexible, though, as it seems that #1 and #2 could be
implemented in user-level code in terms of #3.


Now, I haven't mentioned "^FH" at all, simply because it hasn't been
relevent. Bearword notation has been sufficient for the examples. The
problem with bearwords can be stated simply like thi:

sub foo {
local(*A);
open(A,">abc");
}

Considering the move away from local(), and to my(), and the low-level
nature of globs, this is a bit of an afront. Considering that with refs
globs can now go unused in user-level code, how are we supposed to
explain this bit of "elegance" in the language?

One proposal is to turn FileHandles into official "variables", with a
graspable presence, via the addition of a "^" symbol, used like this:

open(^A,"<foo");
sub bar {
my(^A);
open(^A,">abc");
print ^A "test";
}

One question immediately presents itself: what about formats, and
dirhandles, and maybe compiled regexps in the future. Do all of these get
their own special symbols?

On the other hand, with a slight shift, the above syntax falls directly
into the OO camp:

$A = OOopen("<foo");
sub bar {
my($A);
$A = OOopen(">abc");
print $A "test";
}

This implies that the behavior we want is easily available if we go with
OO capabilities.


At this point, we seem to reach two immediate courses of action:

A. Finish up OO, so that the standard file operations get patched through
as method calls, as in #3 This instantly gives us #1 and #2, as well,
though with less efficiency.

B. Install a simpler mechanism to support #2 and perhaps #1 at the STDIO
level. With a bit of user-level hackery, this will probably give up #3 as
well, but it won't be as efficient as it could be.

A separate goal is:

C. Make FileHandles a separate semantic type, so they can be manipulated
as such.


I guess the final question is: any takers?

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: FileHandle RFD (was Re: "Line Noise" considered offensive) [ In reply to ]
In-Reply-To: <Pine.LNX.3.91.951031023910.3995B-100000@kjahds.com>
Kenneth Albanowski wrote:

> $A = OOopen("<foo");
> sub bar {
> my($A);
> $A = OOopen(">abc");
> print $A "test";
> }

my current 'fudge' for filehandles is something like this:

my $A = \*SomeModule::SOMEMADEUPFILEHANDLENAME;
open($A, ">$abc");
print $A "hello";

or even

my $A = \*STDOUT;

The only problem with this is that of making up unique glob names if the
code is to be reentrant.

To add my 1/2p to the debate, I am not really too concerned about having
another twiddle to denote a filehandle - as has been pointed out, what
about refs to things like REs or anonymous subs?

Perhaps with hindsight, it would have been better to use '^' to
explicitly denote a ref, instead of using '$'. This might look something
like:

my $str = "hello";
my %ary = (1, 2, 3);
my ^r = $str;
$^r = "goodbye";
^r = %ary;
$^ary[1] = 4;

It would certainly make it much easier to read some of the more
complicated bits of code!

Alan Burlison aburlison@cix.compulink.co.uk
Re: FileHandle RFD (was Re: "Line Noise" considered offensive) [ In reply to ]
> From: Kenneth Albanowski <kjahds@kjahds.com>
>
> [.I'm hereby summarizing and pulling together my comments on FileHandle
> stuff. I've decided that things are just to splintered right now to make
> writing large chunks of code (IO::Handle, etc.) a good proposition.
>
> This forms a Request For Discussion, a stopping point for me, until the
> issue reaches some form of resolution. I realize that Perl 6 might be that
> resolution. :-)]

:-)

Maybe not. Read through...

> I'm rapidly getting to be of two minds on this subject: the I/O "SFIO
> discipline" style, where behaviours can be stacked onto a handle, has
> efficiency and simplicity going for it. The OO approach might be more
> flexible.

As I've said elsewhere I believe that SFIO will work 'under the hood' of
stdio and with a narrow scope (read/write/seek/exceptions).

I believe both OO (for user level code) and SFIO (for some whizz-bangs)
are important and complementrary. They can be separate, with no clash.

> The problem, as I see it, is that Perl will definitely need to support the
> following techniques at some point in the future:
>
> 1. A "tied" file handle, without a real underlying handle:
>
> OpenCurses(FH);
> print FH "Abc";
> ioctl FH, ATTRON, "bold"; # For lack of a better OOB call
> close FH;

Why? I see no reason not to use object refs for this kind of new code.

> 2. A tied handle with behaviour added to the standard set:
>
> UUOpen(FH,">>foo.uue");
> print FH "Now is the time...\n";
> close FH;

SFIO would do that by inserting a discipline on a normal filehandle
between a normal open and a normal print. No tie needed.

> If we go the OO route, then these will also need to be supported:
>
> 3. Provide custom "methods", and allow capture of standard methods:
>
> SomeOOOpen(FH,">foo");
> print FH "abc";
> boogle FH 12;
> gentlyclose FH;

See answer to #1.

> 4. Allow OO calling notation:
>
> $a = new SomeOO ">foo";
> $a->print("abc");
> $a->boogle(12);
> $a->gentlyclose();

You've missed the more tricky one:

5. Allow OO calling notation:

print $a "foo";
print $a;

Which, I believe, has to act unchanged for backwards compatibility.
The workaround of print $a $_; is trivial for new code.

> Considering that Perl already has the "FileHandle" class, and lets
> instances of that class (or a derivative) be used as in #4, this seems to
> be a count in favour of OO. But #3 isn't implemented right now, nor is #1
> or #2.

I think #1 and #3 are just a "don't do that - use object refs". #2 is a
natural application for SFIO.

> So... Which of #1, #2, or #3 does someone want to implement first? #2
> seems to consist of very minor changes to the core, perhaps as part of
> installing SFIO. Specifically, each call to file I/O functions would need
> to check for some "tied" marker, and arrange for the callback (perhaps a
> method in a package) to be called.

SFIO would do #2 with, potentially, _no_ changes to perl internals.

> #1 is a bit more complex then #2, as no underlying file handle exists. One
> could always open ">/dev/null", but is this the right approach? This
> style is rather similar to the current tie() approach.
>
> #3 is a completely different set of work, and probably least efficient.
> It is the most flexible, though, as it seems that #1 and #2 could be
> implemented in user-level code in terms of #3.

"don't do that - use object refs"


Here's recommended approach to all these issues:

a. Leave FH style filehandles alone in perl internals (perhaps minor tweaks).

b. Use object refs for new code that needs fancy behaviour. (*)

c. Implement SFIO and use it where appropriate (e.g., #2 uuencode stream)
SFIO will work under-the-hood of both FH and $fh style handles.

This seems to be a simple way forward with low-cost, least surprise and
good functionality. Might even get implemented before Perl6 :)


(*) Something that needs more thought for object refs is 'what to reference'

$obj1 = blessed hash ref
$obj2 = blessed glob ref

print $obj1 "foo";
print $obj2 "foo";

Should print $obj2 invoke the print method or the built-in? I believe that
it must be per-class configurable. Some applications will want to let the
built-ins work for speed, others will need to override them for functionality.

Obviously a non-glob ref must call a method. The current implementation
leaves a window open for this since print $obj1 "foo" says 'Not a GLOB reference'.
That looks like a handy hook for a method call to me!

A class implemented via a GLOB ref should have the choice. I think the
best answer for such classes is to control the behaviour via an
inherited class attribute in the same way that %OVERLOAD works.

This could either be one attribute that applies to all I/O built-ins (simple
and fast) or one attribute per built-in (more complex, possibly slower
and prone to errors if not all builtins are overridden).

It's actually very tempting to suggest that the OVERLOAD mechanism be used
for this. It seems like a rather good fit. Certainly work exploring.


> Now, I haven't mentioned "^FH" at all, simply because it hasn't been relevent.
> [...] the behavior we want is easily available if we go with OO capabilities.

Suits me.


> I guess the final question is: any takers?

I hope Malcolm with run with Paul's SFIO module for awhile. He's certainly
well qualified and I'm _way_ overdrawn on free time.

The OVERLOAD'd I/O built-ins probably needs some discussion. Perhaps
Ilya could comment on the practicality of the suggestions above.

Tim.