我正试图围绕Perl处理print
的参数解析的方式。
为什么会这样
print $fh $stufftowrite
按预期写入文件句柄,但
print($fh, $stufftowrite)
将文件句柄写入STDOUT
而不是?
我的猜测是它与print
的文档中的警告有关:
小心不要使用左括号跟随print关键字,除非您希望相应的右括号终止print的参数;将括号括在所有参数周围(或插入一个+,但看起来不太好)。
我是否应该习惯第一种形式(这对我来说似乎不对,来自于所有使用围绕函数参数的括号的语言),还是有办法告诉Perl做我想做的事情? / p>
到目前为止,我已经在第一,第二和两个参数周围尝试了很多括号组合,但没有成功。
答案 0 :(得分:18)
结构bareword (LIST1), LIST2
表示"将函数bareword
应用于参数LIST1
",而bareword +(LIST1), LIST2
可以,但不是必须表示"将bareword
应用于组合列表LIST1, LIST2
"的参数。这对于分组参数非常重要:
my ($a, $b, $c) = (0..2);
print ($a or $b), $c; # print $b
print +($a or $b), $c; # print $b, $c
前缀+
也可用于区分hashref与块,以及来自裸字的函数,例如:订阅哈希时:$hash{shift}
返回shift
元素,而$hash{+shift}
调用函数shift
并返回值为shift
的哈希元素。
在面向对象的Perl中,通常使用箭头语法调用对象上的方法:
$object->method(LIST); # call `method` on `$object` with args `LIST`.
但是,有可能,但不建议,使用将动词放在首位的间接表示法:
method $object (LIST); # the same, but stupid.
因为类只是它们自身的实例(在语法意义上),所以你也可以调用它们的方法。这就是为什么
new Class (ARGS); # bad style, but pretty
与
相同Class->new(ARGS); # good style, but ugly
但是,这有时会使解析器混淆,因此不建议使用间接样式。
但它确实暗示了印刷品的作用:
print $fh ARGS
与
相同$fh->print(ARGS)
实际上,文件句柄$fh
被视为类IO::Handle
的对象。
(虽然这是一个有效的语法解释,但事实并非如此。IO::Handle
的来源本身使用了行print $this @_;
。打印函数只是定义了这个方式。)
答案 1 :(得分:13)
看起来你有一个错字。您在第二个print语句中的文件句柄和参数之间放了一个逗号。如果这样做,文件句柄将被视为参数。这似乎只适用于词法文件句柄。如果使用全局文件句柄,则会产生致命错误
No comma allowed after filehandle at ...
所以,要明确的是,如果您必须为print
添加括号,请执行以下操作:
print($fh $stufftowrite)
虽然我个人更喜欢不使用括号,除非我必须这样做,因为它们只会增加混乱。
答案 2 :(得分:8)
现代Perl书籍在Chapter 11("要避免什么"),"间接符号标量限制":
中说明语法的另一个危险是解析器需要单个标量表达式作为对象。打印到存储在聚合变量中的文件句柄似乎很明显,但它不是:
# DOES NOT WORK AS WRITTEN
say $config->{output} 'Fun diagnostic message!';
Perl将尝试在$ config对象上调用say。
close
和say
- 所有以文件句柄操作的内置函数 - 以间接方式运行。当文件句柄是包全局变量时,这很好,但是词法文件句柄(Filehandle References)使间接对象语法问题变得明显。要解决此问题,请消除产生预期调用的子表达式的歧义:
say {$config->{output}} 'Fun diagnostic message!';
当然,print({$fh} $stufftowrite)
也是可能的。
答案 3 :(得分:3)
如何定义print
的语法。它真的那么简单。有什么可以解决的。如果在文件句柄和其余参数之间放置逗号,则表达式将解析为print LIST
而不是print FILEHANDLE LIST
。是的,这看起来很奇怪。 非常奇怪。
不被解析为print LIST
的方法是提供一个可以合法解析为print FILEHANDLE LIST
的表达式。如果你要做的是围绕print
的参数括起来使它看起来更像普通的函数调用,你可以说
print($fh $stufftowrite); # note the lack of comma
你也可以说
(print $fh $stufftowrite);
如果您尝试执行的操作是从周围代码中设置print
表达式。关键是包括逗号会改变解析。