在Perl中,我该如何设置$!从函数返回之前?

时间:2017-06-28 19:01:38

标签: perl return

想象一下,我有这个简单的功能

say_hi() || die "ERROR: sub say_hi had an issue: Details => $!\n";

sub say_hi{
   my ($name) = @_;
   return unless $name;
   print "Hi $name\n";
   return 1;
}

如何在sub中设置 $!的内容,以便在函数返回后使用它。我正在尝试做类似于

的事情
open() || die "$!";

一样。谢谢

2 个答案:

答案 0 :(得分:3)

perldoc -v $!

  

引用时,$!检索C“errno”的 当前值               整数变量 。如果为$!分配了一个数值,那么该值               存储在“errno”中。当引用为字符串时,$!会产生               系统错误字符串对应于“errno”。

     

...对$!的分配同样是 短暂的 。它               可以在调用“die()”运算符之前立即使用               设置退出值,或检查系统错误字符串               对应于错误n,或将$!恢复为有意义的状态。 (强调我的

这就解释了为什么你不能做到这一点:

#!/usr/bin/env perl

say_hi() or die "ERROR: sub say_hi had an issue: Details => $!\n";

sub say_hi{
   my ($name) = @_;
   unless ($name) {
       $! = 'no name';
       return;
   }
   print "Hi $name\n";
   return 1;
}

结果是:

  

ERROR: sub say_hi had an issue: Details =>

考虑使用eval / $@

#!/usr/bin/env perl

eval { say_hi() } or die "ERROR: sub say_hi had an issue: Details => $@\n";

sub say_hi{
   my ($name) = @_;
   $name or die "no name\n";
   print "Hi $name\n";
   return 1;
}

另请参阅“Is Try::Tiny still recommended for exception handling in Perl 5.14 or later?

如果你在这个问题的答案中遵循brian的建议,你可以做类似的事情:

#!/usr/bin/env perl

use strict;
use warnings;

my $r = say_hi();

$r->{success}
    or die sprintf "ERROR: sub say_hi had an issue: Details => %s\n", $r->{reason};

sub say_hi{
   my ($name) = @_;
   $name or return { success => 0, reason => 'Missing "name"' };
   print "Hi $name\n";
   return { success => 1 };
}

或者,您可以使用Params::ValidateValidate::Tiny

答案 1 :(得分:3)

$!是C&#39 {s} errno的代理。值errno可以在Errno中作为常量使用。

use Errno qw( EINVAL );

sub foo {
   my ($arg) = @_;
   if (!$arg) {
      $! = EINVAL;
      return 0;
   }

   ...

   return 1;
}

foo(...)
   or die($!);

很少这样做,主要是因为您仅限于为系统调用设计的错误代码。抛出异常或具有特定于模块的错误变量(例如$DBI::err)更为常见。