Hi! Please consider following me on twitter: @hanekomu.
2009年06月10日
PerlIO::via and autovivifying namespaces
PerlIO::via, in perl 5.10.0 at least, has a bug, or let's call
it an unintuitive feature. To start, let's look at this excerpt from its
manpage to see what it should do.
The PerlIO::via module allows you to develop PerlIO layers in Perl,
without having to go into the nitty gritty of programming C with XS as
the interface to Perl.
One example module, PerlIO::via::QuotedPrint, is included with Perl
5.8.0, and more example modules are available from CPAN, such as
PerlIO::via::StripHTML and PerlIO::via::Base64. The
PerlIO::via::StripHTML module for instance, allows you to say:
use PerlIO::via::StripHTML;
open( my $fh, "<:via(StripHTML)", "index.html" );
my @line = <$fh>;
to obtain the text of an HTML-file in an array with all the HTML-tags
automagically removed.
Please note that if the layer is created in the PerlIO::via::
namespace, it does not have to be fully qualified. The PerlIO::via
module will prefix the PerlIO::via:: namespace if the specified
modulename does not exist as a fully qualified module name.
As the manpage later explains, the way to create these I/O layers is to
declare certain subroutines like PUSHED(), OPEN(),
WRITE() or CLOSE() in the layer package.
So I've written a simple layer that uppercases everything that passes
through. Imaginatively, I'm calling this layer Foo, and, for
demonstration purposes, I'm only writing the bare minimum to make it work.
#!/usr/bin/env perl use strict; use warnings; package PerlIO::via::Foo; sub PUSHED { bless {}, shift } sub OPEN { 1 } sub WRITE { print uc $_[1]; length $_[1] } sub CLOSE { 0 } package main; open my $fh, '>:via(Foo)', 'whatever' or die $!; print $fh "Hello\n"; close $fh;
This program runs as expected and prints:
HELLO
To demonstrate the bug, let's add a simple package declaration.
package Foo::Bar;
We didn't declare any subroutines or variables in that package, just the package itself. When we run the program now, it prints:
Function not implemented at ./test.pl line 15.
What's going on?
When we declare the Foo::Bar package, the Foo
namespace seems be autovivified, that is, it seems to magically spring into
existence. PerlIO::via only seems to check whether the unqualified
namespace — Foo in this case — exists and if so,
whether there is a PUSHED() subroutine in it. If there isn't, it
declares ENOSYS, that is, Function not implemented.
It does not try to fallback on the fully qualified namespace —
PerlIO::via::Foo in this case — like AUTOLOAD
would.
I think it should fallback, so I consider it a bug in
PerlIO::via, or at least a very unintuitive feature.
Tags: bug.
posted at: 13:12 | path: /dev | permalink | 0 comments | 0 trackbacks
Comments are closed for this story.
Trackbacks are closed for this story.