Perl Scope与格式/写入混淆

rob*_*but 7 perl scope built-in

如果声明的范围几乎是包级别的话,为什么在声明时$var不可用(超出范围?)?writemy

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

my $var = 'foo';

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


sub test {
    say $var;
    write;
}


1;
Run Code Online (Sandbox Code Playgroud)

叫:

perl -wE 'use ASDF; ASDF::test();'
Run Code Online (Sandbox Code Playgroud)

产品:

foo
Variable "$var" is not available at ASDF.pm line 16.
Use of uninitialized value $var in formline at ASDF.pm line 10.
test :
Run Code Online (Sandbox Code Playgroud)

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

更换myour修复它:

foo
test :    foo
Run Code Online (Sandbox Code Playgroud)

为什么不能正确write接听$var
它是一个范围问题,或用Perl怎样的问题writeformat实现?

Pow*_*eke 2

在Perl 格式文档的底部,它说:

词法变量(用“my”声明)在格式中不可见,除非该格式是在词法变量的范围内声明的。

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

这个关于格式的更现代的教程重复了,如果您使用词法作用域变量(用 声明的变量),您可能会遇到麻烦,my因为 write 从当前包中选择变量,并且如您的问题的注释中所述,是在以下时间编写的Perl 没有my关键字或词法作用域。

文章提供的解决方案:

当您准备好输出一些数据时,可以使用 write。这种设计显示了格式的时代,因为 write 不需要参数来填充图片。它使用范围内的变量。

our( $id, $name, $food, $amount ) = qw( 12 Buster Tuna 1.0 );
write();
Run Code Online (Sandbox Code Playgroud)

格式也有点粗糙,因为你没有传递参数来 write 来填充图片。Perl 依赖于范围内具有指定名称的变量。您可以使用词法变量,但它们必须与格式定义位于同一范围内,并且当您调用 write 时它们必须位于范围内。使用词法来做到这一点是不切实际的,因此最敏捷的方法涉及本地化的包变量:

foreach my $record ( @cats ) {
    local( $id, $name, $food ) = @$record;
    write( $fh );
}
Run Code Online (Sandbox Code Playgroud)

总结中还有这个建议:

  • 使用本地化的包变量来设置格式的数据

所以,如果你想在现代 Perl 中继续使用and ,那么ourandlocal似乎是一个不错的选择。formatwrite