Why is $var
unavailable (out of scope ?) to write
when declared with my
, if its scope is pretty much package-level ?
package ASDF;
use warnings;
use strict;
use feature 'say';
my $var = 'foo';
format =
@<<<<< @>>>>>
'test : ', $var
.
sub test {
say $var;
write;
}
1;
Called with :
perl -wE 'use ASDF; ASDF::test();'
Produces :
foo
Variable "$var" is not available at ASDF.pm line 16.
Use of uninitialized value $var in formline at ASDF.pm line 10.
test :
It appears otherwise available to say
in the same scope ...
Replacing my
with our
fixes it :
foo
test : foo
Why can't write
pick-up on $var
correctly ?
Is it a scope issue, or an issue with how Perl's write
or format
is implemented ?
At the bottom of the Perl format documentation it says:
Lexical variables (declared with "my") are not visible within a format unless the format is declared within the scope of the lexical variable.
Reading that would imply that what you are trying would work, but apparently lexically scoped variables work differently for format
and write
when called from outside of the package they where declared in. Also, all of the examples in the article use global variables...
This more modern tutorial about format repeats that you might run into trouble if you use lexically scoped variables (variables declared with my
) because write picks the variables from the current package and, as stated in the comments of your question, was written in a time when Perl did not have the my
keyword or lexical scoping.
The solutions the article offers:
When you are ready to output some data, you use write. This design shows the age of formats since write doesn't take arguments to fill in the pictures. It uses the variables that are in scope.
our( $id, $name, $food, $amount ) = qw( 12 Buster Tuna 1.0 );
write();
Formats are also a bit crufty because you don't pass arguments to write to fill in the pictures. Perl relies on variables with the specified names being in scope. You can use lexical variables, but they have to be in the same scope as the format definition, and they have to be in scope when you call write. It's impractical to do that with lexicals, so the most agile way involves localized package variables:
foreach my $record ( @cats ) {
local( $id, $name, $food ) = @$record;
write( $fh );
}
And also this advice in the wrap-up:
- Use localized package variables to set data for the format
So, our
and local
seem to be the way to go if you want to keep using format
and write
in modern Perl.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With