创建Perl函数,它接受可选的文件句柄,如内置打印



如果我想获得类似的参数作为内置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->();
   ...
}

我比前两个更喜欢这个解决方案。

最新更新