如何在 perl 子例程签名中设置默认文件句柄?

How can I set a default file handle in a perl subroutine signature?

我有一个子程序,

use experimental "signatures";

sub foo {
  my $fh = +shift;
  open ($fh, '>', 'default_file') unless defined $fh;
}

我想将其移植到子例程签名中。是否可以将 $fh 设置为默认指向 default_file.

的文件句柄

像这样

sub foo ($fh=open($fh,">",foo")) {}

甚至 do{} 块,

sub foo ($fh=do { open($fh,">",foo"), $fh } ) {}

我知道如果我使用或创建一个包装器我可以获得这个语法。但似乎应该有某种方法可以在不调用 IO::File 之类的情况下完成此操作。

等待更好的答案,我认为唯一的方法是使用包装器,

use IO::File;                                                              
sub foo ( $fh=IO::File->new("default_file", "w") ) {                                
  print $fh 42                                                             
}

您展示的第二次尝试几乎有效,您只需要另一个变量来代替,因为分配默认值时 $fh 尚不存在;并 return 它在声明它的地方的单独语句中。您当然可以滥用全局变量来执行此操作,但这很丑陋且有漏洞。

sub foo ($fh=do { open(my $d,">","foo"); $d } ) {}

这当然应该有错误处理。

sub foo ($fh=do { open(my $d,">","foo") or die "Failed to open 'foo': $!"; $d } ) {}

A proposed extension to signatures 可以用来做一些稍微不同的事情,但我不确定这是否更好:

sub foo (?$d, $fh=(open($d,">","foo") || die "Failed to open 'foo': $!", $d) ) {}

也可以作弊,只是一点点,使用无名无值optional argument

use experimental "signatures";

sub foo ($=) {
    my $fh = shift;
    open $fh, '>', "foo.txt" or die $!  if not defined $fh;
    say $fh 42;
    return $fh;
}

从处理参数 "normally" 的意义上来说,这是伪造的(就像没有签名一样)。然而,签名的好处之一是 @_ 保持原始状态,也可以使用

When using a signature, the arguments are still available in the special array variable @_, in addition to the lexical variables of the signature.

我没有看到不使用它的充分理由。 即使它将参数处理推回到子体中,您仍然可以获得签名的其他好处 - - 以及额外的灵活性措施。


处理签名中参数的风格点,包括它们的默认值,在这里无论如何都被拒绝了,仅仅因为这个默认值有多少要做。