Perl 作用域与格式/写入的混淆

Perl Scope Confusion with Format / Write

为什么 $var 在使用 my 声明时对 write 不可用(超出范围?),如果它的范围几乎是包级的?

package ASDF;
use warnings;
use strict;
use feature 'say';

my $var = 'foo';

format =
@<<<<< @>>>>>
'test : ', $var
.


sub test {
    say $var;
    write;
}


1;

调用方式:

perl -wE 'use ASDF; ASDF::test();'

产生:

foo
Variable "$var" is not available at ASDF.pm line 16.
Use of uninitialized value $var in formline at ASDF.pm line 10.
test :

它似乎在同一范围内对 say 可用...

our 替换 my 修复它:

foo
test :    foo

为什么 write 无法在 $var 正确接机?
是范围问题,还是 Perl 的 writeformat 是如何实现的问题?

Perl format documentation 的底部写着:

Lexical variables (declared with "my") are not visible within a format unless the format is declared within the scope of the lexical variable.

阅读这意味着你正在尝试的是可行的,但显然词法范围的变量在 formatwrite 中的工作方式不同,当从它们声明的包外部调用时。另外,本文中的所有示例都使用了全局变量...

This more modern tutorial about format 重复说如果你使用词法范围的变量(用 my 声明的变量)你可能 运行 会遇到麻烦,因为 write 从当前包中挑选变量,并且如前所述在你的问题的评论中,是在 Perl 没有 my 关键字或词法范围的时候写的。

文章提供的解决方案:

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 );
}

总结中还有这个建议:

  • Use localized package variables to set data for the format

因此,如果您想在现代 Perl 中继续使用 formatwriteourlocal 似乎是可行的方法。