V
Veli-Pekka Tätilä
Hi,
Browsing perldiag, I noticed messages related to format references. So being
curious and wishing to continue my exploration of Perl's dark and archaic
corners, I decided to write a sample program to see how format references
could be used in Perl. first is an account of what I've attempted, the
relevant code in small chunks and the output received. The mail ends with
the full program source and output from a sample run.
Curiously, references to formats are not documented in perlref, perlform
etc... I'm running ActiveState Perl v5.8.7 (build 815, XP Pro SP2 English).
And now to the program:
To motivate taking references to formats I started out with a rather useless
toy function that generates formats using eval. The format name and the
number of chars it extracts from a global named $text can be parameterized.
sub genForm
{ # A simple format named $name outputting $n chars of $text.
my($name, $length) = @_;
eval
(
"format $name =\nFirst $length chars: @" .
'<' x $length . "\n\$text\n."
); # eval
die $@ unless $@ eq ''; # Eval failed.
} # sub
There's a related output function, which given a format name, writes it out
to the default file handle:
sub writeForm
{ # Write out the specified format.
local $~ = shift;
write;
} # sub
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:umper 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 = ;
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.
The first thing that occurred to me was to try assigning a format reference
to $~, as opposed to a format name. The same writeForm function could be
used, just passing it a reference:
eval { writeForm($formRef) };
print "Using formref for $~: $@";
This strategy didn't work all that well. The statement printing the eval
error outputs:
Using formref for STDOUT: Undefined format "FORMAT(0x18c4eb4)" called at
C:\programming\plx\test.plx line 29.
Apparently no magical dereferencing is going on here. Starting to run out of
ideas, I thought of testing what would happen if I tried to dereference the
format as a scalar. I have no real rationale for that apart from scalar
derefs working for elements in arrays and hashes. I did realize right from
the start this wouldn't work for formats but typed in the following
nevertheless:
eval { writeForm(${$formRef}) };
print "Using desperate scalar deref for $~: $@";
And the output is:
Using desperate scalar deref for STDOUT: Not a format reference at
C:\programming\plx\test.plx line 29.
Quite right, not a format reference. But the thing that puzzles me here is
that the error is phrased as though Perl expected a format reference. Yet
when I give it one, as in the previous attempt, it doesn't seem to like it
any better, either. It just takes the stringified form of the reference to
be a format name which is no good.
Finally, here's the full code followed by some sample output:
Full code:
use strict; use warnings;
use Data:umper;
our $text = 'this is a test';
(my $name, local $\) = ('eight', "\n");
genForm($name , 8);
writeForm($name);
my $formRef = *{ $::{$name} }{FORMAT}; # *foo{FORMAT} syntax in main
package.
dumpForm($formRef);
# Try using formatref in stead of format name for writing the data.
eval { writeForm($formRef) };
print "Using formref for $~: $@";
eval { writeForm(${$formRef}) };
print "Using desperate scalar deref for $~: $@";
sub genForm
{ # A simple format named $name outputting $n chars of $text.
my($name, $length) = @_;
eval
(
"format $name =\nFirst $length chars: @" .
'<' x $length . "\n\$text\n."
); # eval
die $@ unless $@ eq ''; # Eval failed.
} # sub
sub writeForm
{ # Write out the specified format.
local $~ = shift;
write;
} # sub
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
Sample output:
First 8 chars: this is a
The formref eight is:
Stringified: FORMAT(0x18c4eb4)
of type: FORMAT
Dumped:
cannot handle ref type 14 at C:/Perl/lib/Data/Dumper.pm line 167.
$VAR1 = ;
Using formref for STDOUT: Undefined format "FORMAT(0x18c4eb4)" called at
C:\programming\plx\test.plx line 29.
Use of uninitialized value in scalar assignment at
C:\programming\plx\test.plx line 28.
Using desperate scalar deref for STDOUT: Not a format reference at
C:\programming\plx\test.plx line 29.
Browsing perldiag, I noticed messages related to format references. So being
curious and wishing to continue my exploration of Perl's dark and archaic
corners, I decided to write a sample program to see how format references
could be used in Perl. first is an account of what I've attempted, the
relevant code in small chunks and the output received. The mail ends with
the full program source and output from a sample run.
Curiously, references to formats are not documented in perlref, perlform
etc... I'm running ActiveState Perl v5.8.7 (build 815, XP Pro SP2 English).
And now to the program:
To motivate taking references to formats I started out with a rather useless
toy function that generates formats using eval. The format name and the
number of chars it extracts from a global named $text can be parameterized.
sub genForm
{ # A simple format named $name outputting $n chars of $text.
my($name, $length) = @_;
eval
(
"format $name =\nFirst $length chars: @" .
'<' x $length . "\n\$text\n."
); # eval
die $@ unless $@ eq ''; # Eval failed.
} # sub
There's a related output function, which given a format name, writes it out
to the default file handle:
sub writeForm
{ # Write out the specified format.
local $~ = shift;
write;
} # sub
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:umper 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 = ;
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.
The first thing that occurred to me was to try assigning a format reference
to $~, as opposed to a format name. The same writeForm function could be
used, just passing it a reference:
eval { writeForm($formRef) };
print "Using formref for $~: $@";
This strategy didn't work all that well. The statement printing the eval
error outputs:
Using formref for STDOUT: Undefined format "FORMAT(0x18c4eb4)" called at
C:\programming\plx\test.plx line 29.
Apparently no magical dereferencing is going on here. Starting to run out of
ideas, I thought of testing what would happen if I tried to dereference the
format as a scalar. I have no real rationale for that apart from scalar
derefs working for elements in arrays and hashes. I did realize right from
the start this wouldn't work for formats but typed in the following
nevertheless:
eval { writeForm(${$formRef}) };
print "Using desperate scalar deref for $~: $@";
And the output is:
Using desperate scalar deref for STDOUT: Not a format reference at
C:\programming\plx\test.plx line 29.
Quite right, not a format reference. But the thing that puzzles me here is
that the error is phrased as though Perl expected a format reference. Yet
when I give it one, as in the previous attempt, it doesn't seem to like it
any better, either. It just takes the stringified form of the reference to
be a format name which is no good.
Finally, here's the full code followed by some sample output:
Full code:
use strict; use warnings;
use Data:umper;
our $text = 'this is a test';
(my $name, local $\) = ('eight', "\n");
genForm($name , 8);
writeForm($name);
my $formRef = *{ $::{$name} }{FORMAT}; # *foo{FORMAT} syntax in main
package.
dumpForm($formRef);
# Try using formatref in stead of format name for writing the data.
eval { writeForm($formRef) };
print "Using formref for $~: $@";
eval { writeForm(${$formRef}) };
print "Using desperate scalar deref for $~: $@";
sub genForm
{ # A simple format named $name outputting $n chars of $text.
my($name, $length) = @_;
eval
(
"format $name =\nFirst $length chars: @" .
'<' x $length . "\n\$text\n."
); # eval
die $@ unless $@ eq ''; # Eval failed.
} # sub
sub writeForm
{ # Write out the specified format.
local $~ = shift;
write;
} # sub
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
Sample output:
First 8 chars: this is a
The formref eight is:
Stringified: FORMAT(0x18c4eb4)
of type: FORMAT
Dumped:
cannot handle ref type 14 at C:/Perl/lib/Data/Dumper.pm line 167.
$VAR1 = ;
Using formref for STDOUT: Undefined format "FORMAT(0x18c4eb4)" called at
C:\programming\plx\test.plx line 29.
Use of uninitialized value in scalar assignment at
C:\programming\plx\test.plx line 28.
Using desperate scalar deref for STDOUT: Not a format reference at
C:\programming\plx\test.plx line 29.