Re: Using References to Formats?



Veli-Pekka Tätilä wrote:

(snipped)

At this point I started wondering whether I could use a real reference to a
format in stead of an "indirect format" (in analogy to indirect file
handles). First I had to use the *foo{THING} syntax to get at a format. The
following statement, using main's symbol table and *foo{FORMAT} did the
trick for me:

my $formRef = *{ $::{$name} }{FORMAT}; # *foo{FORMAT} syntax in main
package.

To test what info could be gleaned from a format reference I made a function
for that, too. Here it is:

sub dumpForm
{ # Dump info on a format reference.
my $formRef = shift;
print "The formref $name is:";
print "Stringified: $formRef";
print "of type: " . ref($formRef);
print "Dumped: ";
eval { print Dumper($formRef) };
} # sub

Oddly, neither the docs for the ref built-in nor Data::Dumper mentioned
references to formats. Despite this the ref function and stringification
worked all right but Dumper didn't. Here's some output:

The formref eight is:
Stringified: FORMAT(0x18c4ecc)
of type: FORMAT
Dumped:
cannot handle ref type 14 at C:/Perl/lib/Data/Dumper.pm line 167.
$VAR1 = ;


You can use Devel::Peek instead of Data::Dumper
if you want to look at the guts of a format reference.

For me Devel::Peek::Dump prints:

SV = RV(0x1821258) at 0x182ad40
REFCNT = 1
FLAGS = (PADBUSY,PADMY,ROK)
RV = 0x182ae60
SV = PVFM(0x4489e0) at 0x182ae60
REFCNT = 3
FLAGS = (CLONE)
IV = 0
NV = 0
COMP_STASH = 0x0
START = 0x448b90 ===> 5120
ROOT = 0x448c90
XSUB = 0x0
XSUBANY = 0
GVGV::GV = 0x182ae9c "main" :: "eight"
etc.,




I wonder if the debugger does any better. I have not tested it yet.

To make format references useful at all, I suppose one would have to be able
to dereference them somehow. IS that possible, and if so how? Formats have
no sigil so I myself have absolutely no idea how they could be dereferenced.
Would being able to work with format references bring any benefits compared
to refering to formats by name? I suppose not though using format references
does seem to sort of work.


Well, just use another typeglob for dereferencing.
Throw in the 'reftype' function from the
Scalar::Util module and then you can
pass either a format NAME or format
reference to writeForm:


sub writeForm
{ # Write out the specified format.
local $~ = shift;
write;
} # sub


becomes:

use Scalar::Utiil ('reftype');

sub writeForm {
if (reftype $_[0] and reftype $_[0] eq 'FORMAT') {
local *FOO;
*FOO = $_[0];
local $~ = 'FOO';
write;
} else {
local $~ = shift;
write;
}
}

--
Hope this helps,
Steven

.



Relevant Pages