【问题标题】:How to know if perl subroutine takes parameters如何知道perl子程序是否带参数
【发布时间】:2014-12-12 04:15:49
【问题描述】:

我对 perl 很陌生,我似乎找不到任何关于如何知道子例程是否接受参数的信息。

在其他语言中(例如python、java等),很清楚,一个方法/函数通常是这样的:

    def my_func(arg1, arg2):
        # do something

但在 perl 中,它很简单:

    sub my_func {
        my params = @_;
        # do something
    }

但是我看到了一些例子,其中 my params = @_ 甚至不包括在内,但子例程被调用并传递了一个参数。

例如

    sub my_func {
        my $self = shift;
        my $fieldstr = 'tbl'.$self->db_func.'*,';
        my $sql = "SELECT $fieldstr FROM tbl".$self->db_func.'WHERE'.$self->...;

        my $sth = $self->other_func->my_func($sql) or return undef;
    }

所以我想知道是否有某种准则可以知道子例程是否需要参数?

【问题讨论】:

  • shift 在 sub 中与 shift(@_) 相同。
  • 通常,任何子或方法的文档都应该指出参数是什么。 (不想刻薄。)
  • 你是说你根本不懂 Perl,但需要记录一些 Perl 代码? 没有办法通过阅读和理解代码了解 Perl 子例程在其参数列表中的期望。

标签: perl parameters subroutine


【解决方案1】:

请看my answer to a similar question

Perl 非常灵活,因为子例程可以简单地忽略多余的参数,为缺少的参数提供默认值,或者如果参数与预期的完全不符,则die

Perl 的作者Larry Wall 是一位语言学家,其基本原理是子程序的行为类似于命令式动词;所以就像你可以说“取木头”“从棚子后面取木头”“使用拖拉机”,你也可以这么说

fetch($wood)
fetch($wood, $shed)
fetch($wood, $shed, $tractor)

甚至

fetch($wood, {from => 'shed', using => 'tractor'})

这取决于子例程来确定所需的内容。

应避免使用子例程原型,因为它们具有以不明显方式改变代码行为的副作用。它们仅用于编写额外的语言结构;一个很好的例子是Try::Tiny

【讨论】:

  • 但我需要知道一种方法来确定甚至需要一个参数。我在我的一个 cmets 中提到,我正在制作一份系统设计文档。因此,为了准确记录每个函数,我需要在查看特定函数时知道它是否需要参数。否则,每次我发现它被调用/传递一个参数时,我都必须继续返回同一个文件并对其进行编辑。
  • 他问的是如何识别函数的参数,而不是如何强制/验证它们。
  • @yob-v-u 同样,all 子例程采用 尽可能多的参数,只要你给它。在子例程的定义中没有指定调用时应该给出多少参数,因为 Perl 不强制执行任何类似的事情。每个子例程只接收一个存储在本地数组@_ 中的列表,其中包含在命令行上传递的参数。
  • @yob-vu:回复 “我在我的一个 cmets 中提到,我正在制作一份系统设计文档”,如果这对你的问题很重要的话那么您应该编辑您的问题以包含它。
【解决方案2】:

参数在@_ 中传递,因此您需要寻找@_ 的用途。例如,

  • my ($x, $y) = @_;
  • 子中的shiftshift(@_) 相同
  • $_[$i]
  • &f(但不是&f()),如sub log_warn { unshift @_, 'warn'; &log }

作为一个子作者,您应该尽可能在靠近子顶部的地方使用它们,以使它们明显。最后两个通常用作优化或具有引用参数。

【讨论】:

  • 你说我需要寻找@_的用途。但@_ 不包含在函数中
  • 并非所有@_ 的使用都需要@_ 存在。阅读我的其余答案,我在其中列出了可以使用 @_ 的其他三种方式。
【解决方案3】:

子程序调用的参数包含在数组@_中。

数组操作的两个重要函数是shiftpop。假设您有一个列表 (1, 2, 3, 4)。 shift 从列表左侧移除一个值并返回它。

my @list = ( 1, 2, 3, 4 );

my $value = shift @list;

print "$value\n";    # will print "1"
print "@list\n";     # will print "2 3 4"

pop 从右侧而不是左侧做同样的事情:

my @list = ( 1, 2, 3, 4 );

my $value = pop @list;

print "$value\n";    # will print "4"
print "@list\n";     # will print "1 2 3"

在子程序中使用时,popshift 默认使用 @_ 数组:

some_function( 'James', 99 );    #these 2 arguments will be passed to the function in "@_"

sub some_function {
    my $name = shift;             #remove 'James' from list @_ and store it in $name
    my $age  = shift;             #remove 99 from list @_ and store it in $age
    print "Your name is $name and your age is $age\n";
}

【讨论】:

  • 您能否在示例顶部重述您的问题?不清楚您在写什么。
  • @JasonD 什么都没问,因为这是一个答案,而不是一个问题。
  • 请不要使用& 调用函数(请参阅this questionthis answer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 2012-11-11
相关资源
最近更新 更多