perl - 子程序是否应该始终显式返回?

标签 perl function oop subroutine perl-critic

如果perlcritic说“在 sub 中没有返回是错误的”,如果真的不需要它们,还有什么选择?

我养成了两个明显的坏习惯:

  • 我明确地将变量分配给“$main::”命名空间。
  • 然后我在 subs 中使用这些变量。

例如,我可能会..

#!/usr/bin/perl
use strict;
use warnings;

@main::array = (1,4,2,6,1,8,5,5,2);

&sort_array;
&push_array;
&pop_array;

sub sort_array{
    @main::array = sort @main::array;
    for (@main::array){
        print "$_\n";
    }
}

sub push_array{
    for ( 1 .. 9 ){
        push @main::array, $_;
    }
}

sub pop_array {
    for ( 1 .. 3 ){
        pop @main::array;
    }
}

我不经常这样做。但在上面,这是有道理的,因为我可以隔离操作,而不必担心来回传递值,而且它对我来说通常看起来很整洁。

但正如我所说,perl 评论家说它错了 - 因为没有返回..

那么,是否有人能够解释我正在尝试做的事情并提出一种更好的方法来处理这种 perl 编码风格?例如。我是在做 OOP 吗?

最佳答案

简而言之 - 是的,您基本上是在进行 OO,但以一种会让所有人感到困惑的方式。

像那样做潜艇的危险在于你是在远距离行动。这是一种糟糕的编码风格,必须完全在其他地方寻找可能会破坏您的代码的内容。

这通常就是为什么要尽可能避免“全局变量”的原因。

对于一个简短的脚本,太多并不重要。

关于返回值 - Perl 默认返回最后一个表达式的结果。 (参见:return)

(In the absence of an explicit return, a subroutine, eval, or do FILE automatically returns the value of the last expression evaluated.)

原因Perl critic标记它是:

Require all subroutines to terminate explicitly with one of the following: return, carp, croak, die, exec, exit, goto, or throw.

Subroutines without explicit return statements at their ends can be confusing. It can be challenging to deduce what the return value will be.

Furthermore, if the programmer did not mean for there to be a significant return value, and omits a return statement, some of the subroutine's inner data can leak to the outside.

虽然 Perlcritic 并不总是正确的 - 如果有充分的理由做你正在做的事情,然后将其关闭。只要您考虑过并意识到风险和后果。

我个人认为显式返回某些东西是更好的风格,即使它只是return;

无论如何,以(粗略的)面向对象的方式重新起草您的代码:

#!/usr/bin/perl
use strict;
use warnings;

package MyArray;

my $default_array = [ 1,4,2,6,1,8,5,5,2 ];

sub new {
   my ( $class ) = @_;
   my $self = {};
   $self -> {myarray} = $default_array;
   bless ( $self, $class );
   return $self;
}

sub get_array { 
   my ( $self ) = @_;
   return ( $self -> {myarray} ); 
}

sub sort_array{
    my ( $self ) = @_;
    @{ $self -> {myarray} } = sort ( @{ $self -> {myarray} } );
    
    for ( @{ $self -> {myarray} } ) {
        print $_,"\n";
    }
    return 1;
}

sub push_array{
    my ( $self ) = @_;
    for ( 1 .. 9 ){
        push @{$self -> {myarray}}, $_;
    }
    return 1;
}

sub pop_array {
    my ( $self ) = @_;
    for ( 1 .. 3 ){
        pop @{$self -> {myarray}};
    }
    return 1;
}

1;

然后调用它:

#!/usr/bin/perl

use strict;
use warnings;

use MyArray;

my $array = MyArray -> new();

print "Started:\n";
print join (",", @{ $array -> get_array()} ),"\n";

print "Reshuffling:\n";
$array -> sort_array();

$array -> push_array();
$array -> pop_array();

print "Finished:\n";
print join (",", @{ $array -> get_array()} ),"\n";

它可能会稍微整理一下,但希望这能说明 - 在您的对象中,您有一个内部“数组”,然后您可以通过调用来“处理”。

结果大致相同(我想我已经复制了逻辑,但不要完全相信它!)但是你有一个独立的事情在进行。

关于perl - 子程序是否应该始终显式返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28761824/

相关文章:

Perl:如何跳出嵌套循环?

c++ - 错误 : No matching function found

javascript - 分解为更小的功能 MVC

C++:从子对象到父对象的信息传播

php oop mysql 查询

mysql - Perl CGI::Session MySQL 解冻 utf-8 数据

perl - 如何将参数从 plack 应用程序传递到在 builder 中启用的 mojolicious 应用程序?

function - 如何将结构作为函数的参数传递

php - 使用主键以外字段的 Yii 模型关系

linux - 使用 Perl 在 linux(和 windows)上读取密码保护的 XLSX