如果我想获得类似的参数作为内置print
传递,例如接受可选的第一个参数(即文件句柄(如何声明函数原型?例如,调用语法将为 myprint $filehandle @mylist
。
print $fh @list
作为间接方法调用的示例,等效于
$fh->print(@list)
若要使用可通过文件句柄间接调用的其他函数,请在IO::Handle
包中定义它。
sub IO::Handle::myprint {
my ($self, @list) = @_;
#$self->print(scalar localtime,": ",@list);
print $self scalar localtime, ": ", @list;
}
open my $fh, '>', 'foo';
print $fh "hellon"; # IO::Handle::print($fh, "hellon")
myprint $fh "worldn"; # IO::Handle::myprint($fh, "worldn")
close $fh;
这适用于 Perl v5.16 及更高版本,不适用于 Perl v5.12 及更早版本,原因我没有调查过(也许是因为直到 v5.14 或 v5.16 所有文件句柄才自动祝福到 IO::File
中(
这似乎适用于所有版本的 Perl 至少到 v5.8。这是myprint
方法内部的语法$self->print(...)
需要 v5.16(或者可能是 v5.14,只要所有文件句柄都自动祝福为 IO::File
(——print $self ...
仍然适用于旧的 Perls。
print
的语法不能被 Perl subs 复制。
$ perl -le'print defined(prototype("CORE::print")) ? "Can" : "Can'''t", " be replicated"'
Can't be replicated
具体来说,语法NAME EXPR LIST
不能用于调用 Perl sub,因为语法用于间接方法调用。 NAME EXPR LIST
已经意味着EXPR->NAME(LIST)
选项 1
# myprint $fh, LIST
# myprint *FH, LIST
# myprint *FH, LIST
sub myprint {
my $fh = shift;
...
}
选项 2
# myprint $fh, LIST
# myprint *FH, LIST
# myprint *FH, LIST
# myprint FH, LIST
sub myprint(*@) {
my $fh = shift;
if (!ref($fh)) {
$fh = caller().'::'.$fh if $fh !~ /^(?:ARGV|STD(?:IN|OUT|ERR))z/;
no strict qw( refs );
$fh = *$fh;
}
...
}
另一方面,即使是print
实际上也不支持 print EXPR LIST
.它支持以下语法:
print LIST # Short for: print { select() } LIST
print IDENT LIST # Short for: print { *IDENT } LIST
print $VAR LIST # Short for: print { $VAR } LIST
print BLOCK LIST
您实际上可以支持最终形式的print
(其他形式只是快捷方式(:
# myprint { select } LIST
# myprint { $fh } LIST
# myprint { *FH } LIST
# myprint { *FH } LIST
sub myprint(&@) {
my $fh = shift->();
...
}
我比前两个更喜欢这个解决方案。