perl:为什么不回归0或1?

cha*_*luo 2 perl

我正在使用哈希表实现perl fib:

#!/usr/bin/perl

use strict;
use warnings;
no warnings 'recursion';

my %m_fib = (0,1,1,1);

while (my $a = <STDIN>) {
    print "--".&fib($a)."\n";
}

sub fib {
    foreach my $i (@_) {
        if (not defined $m_fib{$i}) {
            $m_fib{$i} = &fib($i - 1) + &fib($i - 2);
        }
        return $m_fib{$i};
    }
}
Run Code Online (Sandbox Code Playgroud)

输入大于1时效果很好,但默认为0或1.

哈希应该没问题,因为它返回了正确的结果,但是如果我用0或1提供它,为什么它不起作用?

Mat*_*teo 6

您的输入包含行尾(\n).删除它chomp(文档)

while (my $a = <STDIN>) {
    chomp $a;
    print "--".&fib($a)."\n";
}
Run Code Online (Sandbox Code Playgroud)

编辑:问题是什么

  • 对于任何输入,defined测试将始终失败,因为字符串number\n不存在于散列中

  • Perl是能够与您的输入进行数学运算20\n - 119

  • 现在有01没有定义的值被发现,你的代码将调用fib(-1)fib(-2)fib(0)fib(-1)分别.这将产生无限循环.

  • 用2测试将失败和Perl将执行减法调用fib(1) + fib(0)(所述\n).在第二次调用中,您的测试将$m_fib(0)确实存在.

编辑2

一个小评论,有一些评论

  • 你的函数处理多个参数但在第一个参数之后退出.你永远不会用多个参数调用它(即使你做了它也永远不会处理第二个参数)

  • 内联的其他一些注释(你可以使用Perl :: Critic查看代码)

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    # Not needed
    # no warnings 'recursion';
    
    my %m_fib = ( 0, 1, 1, 1 );
    
    # From Perl::Critic
    #
    # Use "<>" or "<ARGV>" or a prompting module instead of "<STDIN>" at line 10, column 17.
    #   InputOutput::ProhibitExplicitStdin (Severity: 4)
    #     Perl has a useful magic filehandle called `*ARGV' that checks the
    #     command line and if there are any arguments, opens and reads those as
    #     files. If there are no arguments, `*ARGV' behaves like `*STDIN' instead.
    #     This behavior is almost always what you want if you want to create a
    #     program that reads from `STDIN'. This is often written in one of the
    #     following two equivalent forms:
    #
    #     while (<ARGV>) {
    #       # ... do something with each input line ...
    #     }
    #     # or, equivalently:
    #     while (<>) {
    #       # ... do something with each input line ...
    #     }
    #
    #   If you want to prompt for user input, try special purpose modules like
    #   IO::Prompt.
    
    while ( my $a = <> ) {
        chomp $a;
    
        # use " just when needed
        print '--' . fib($a) . "\n";
    }
    
    sub fib {
    
        my $i = shift;
    
        if ( not defined $m_fib{$i} ) {
    
            # it is not necessary to use & for subroutine calls and
            # can be confused with the logical and
    
            $m_fib{$i} = fib( $i - 1 ) + fib( $i - 2 );
        }
        return $m_fib{$i};
    
    }
    
    Run Code Online (Sandbox Code Playgroud)