当没有遇到return语句时,Perl从子例程返回什么?

时间:2017-07-17 21:40:33

标签: perl

我今天遇到了这个问题并认为发布Q& A是谨慎的,因为我找不到类似的东西。
如果您发现此问题的副本,请随时投票决定。

以下子程序有条件地return输出;我认为它“笨拙”,因为当条件不满足时,它不清楚返回给调用者的内容:

sub is_multiple_of_three {

    my ( $value ) = @_ ;
    return "$value is a multiple of 3"
      unless $value % 3;
}

快速重写可以在所有情况下简化(更优雅)子程序的预期行为:

sub is_multiple_of_three { 

    my ( $value ) = @_ ;
    return if $value % 3;
    return "$value is a multiple of 3";
}

当调用这两个子程序时,我希望在列表上下文中的return之间找到一些一致性:

  • 条件评估为真时的字符串
  • 条件评估为false时没有(空列表)

但是,唉,这种行为有些出乎意料:

use strict;
use warnings;
use Data::Printer;
use feature 'say';

my %subs = (
            graceful => sub {
                            my ( $value ) = @_ ;
                            return if $value % 3;
                            return "$value is a multiple of 3";
                        },

              clumsy => sub {
                            my ( $value ) = @_ ;
                            return "$value is a multiple of 3"
                              unless $value % 3;
                        },
           );

for my $name ( keys %subs ) {

    my $sub = $subs{$name};
    say $name;
    my @results = map { $sub->($_) } 1 .. 10;
    p @results;
}

输出

graceful
[
    [0] "3 is a multiple of 3",
    [1] "6 is a multiple of 3",
    [2] "9 is a multiple of 3"
]
clumsy
[
    [0] 1,
    [1] 2,
    [2] "3 is a multiple of 3",
    [3] 1,
    [4] 2,
    [5] "6 is a multiple of 3",
    [6] 1,
    [7] 2,
    [8] "9 is a multiple of 3",
    [9] 1
]

问题

“graceful”风格的行为符合预期,但为什么“条件为假”时“笨拙”子返回整数?

2 个答案:

答案 0 :(得分:5)

行为与perldoc perlsub

中记录的内容一致
  

可以选择使用return语句来退出子例程   指定返回值,将在。中计算   适当的上下文(列表,标量或无效)取决于上下文   子程序调用。 如果指定无返回值,则子例程   返回列表上下文中的空列表 ,标量中的未定义值   上下文,或无空间背景中的任何内容如果您返回一个或多个   聚合(数组和散列),这些将被拼合成   一个无法区分的大名单。

     

如果 未找到任何返回,并且最后一个语句是表达式,则返回其值 。如果最后一个语句是循环控制结构,如foreachwhile,则返回的值未指定。空子返回空列表。

优雅的列表上下文

  • True :返回字符串"$value is a multiple of 3"已返回

  • 错误:返回空列表

这就是@results中只有三个元素的原因;只有当条件计算结果为true时,才会向数组添加某些内容。

列表上下文中的笨拙子

  • True :返回返回字符串"$value is a multiple of 3"。这里没有戏剧。
  • 错误:由于未遇到显式return,因此返回上次评估的表达式的值$value % 3

因此,在这两种情况下,子程序都会返回一个值,这就是@results中有十个项目的原因。

答案 1 :(得分:1)

出于最后表达的目的,foo if barif (bar) { foo }等同于bar and foo,同样,除非等同于或。