Perl子例程和数组

时间:2012-08-12 20:45:16

标签: arrays perl subroutine

我刚开始使用在线教程开始Perl(约15分钟前)。我做了一个小子例程来测试一些Perl功能,并想知道是否可以在运行时确定传递给子'调用的参数是数组还是标量。让我们使用我写的子作为例子:

#!/usr/bin/perl

sub somme_prod {
    if (scalar(@_) > 1) {
        $facteur = shift(@_);
        foreach my $nb (@_) {
            $resultat += $nb
        }
        return ($resultat * $facteur);
    }
    else {
        return "ERREUR";
    }
}

print somme_prod(2, 2, 3, 7);

这是一个基本的sum-product子程序,它正如它的名字所说的那样。现在,是否可以修改此子例程以允许混合使用这样的数组和标量?

somme_prod(2, (2,3), 7);
somme_prod(2, (2,3,7));
#...

此外,对此处演示的Perl编码风格的任何评论都是很多欢迎。我有业余C ++编码的背景,所以我可能不会在Perl中思考。

编辑:我很抱歉。我实际上在发布后尝试它,似乎Perl确实处理了我想要它的sub。现在我想我的问题会更多“Perl如何知道如何处理这个”?

编辑更多Perl-ish版本的代码。

3 个答案:

答案 0 :(得分:2)

是;在Perl中,您可以创建对数组(或哈希或其他任何内容)的引用,以将多个值填充到单个参数中。

例如:

somme_prod(2, [2, 3], 7);

......将决定:

sub somme_prod {
  foreach my $arg (@_) {
    if (ref($arg) eq 'ARRAY') {
      my @values = @$arg; # dereference, e.g. [2, 3] -> (2, 3)
      . . .
    } else {
      # single value, e.g. "2" or "7"
    }
  }
}

您可以阅读perldoc perlref页面以了解有关参考资料的所有信息。

答案 1 :(得分:2)

Perl以不同的方式处理列表和数组,您可以阅读的有用文档是What is the difference between a list and an array?

Perl 总是展平嵌套列表(以及列表中的数组)所以

my @data1 = (2, (2, 3), 7);

my @data2 = (2, 3);
my @data1 = (2, @data2, 7);

相当于

my @data1 = (2, 2, 3, 7);

正如凯文所说,如果你想要嵌套数组,你必须在子列表出现的位置放置一个数组 reference 。因为引用是标量,所以它不会被扩展。

您的子程序很好,但使用一些事实上的标准可以帮助其他人遵循您的程序。首先,惯例是如果出现错误,子例程将返回undef,以便您可以编写

sous_routine($p1, $p2) or die "Erreur";

在这种情况下,零是有效结果的可能性破坏了这一点,但仍然最好遵守规则。没有参数的普通return表示错误

稍微整理一下,并使用unlessif作为语句修饰符给出了这个

sub somme_prod {
  return unless @_ > 1;
  my $facteur = shift;
  my $somme = 0;
  $somme += $_ for @_;
  return $somme * $facteur;
}

print somme_prod(2, 2, 3, 7);

答案 2 :(得分:0)

你认识Perl 15分钟?暂时忘掉引用

基本上,传递给子程序的所有内容都是一个数组。实际上,它存储在一个名为@_的数组中。

# /usr/bin/env perl

use strict;   #ALWAYS USE!
use warnings; #ALWAYS USE!

my @array = qw(member1 member2 member3 member4);

foo(@array, 'scalar', 'scalar', 'scalar');

sub foo {

print "My input is " . join (":", @_) . "\n";

这将打印:

my input is member1:member2:member3:member4:scalar:scalar:scalar

无法判断哪些条目来自数组,哪些条目来自标量。就子程序而言,它们都是数组@_的所有成员。


顺便说一句,Perl附带了一个名为perldoc的命令。当有人说要查看perlref时,您可以在命令行输入perldoc perlref并查看文档。您也可以访问网站http://perldoc.perl.org,该网站还包含perldoc命令中的相同信息。


现在关于参考....

Perl数组的数据元素或哈希值只能包含单个值。这可以是一个字符串,它可以是一个实数,它可以是一个整数,它可以是另一个Perl数据结构的引用。这就是所有的乐趣和金钱。

例如,上面的相同子例程foo可以获取此信息:

foo(\@array, 'scalar', 'scalar', 'scalar'); #Note the backslash!

在这种情况下,您不会将@array的值传入foo。相反,对数组的引用作为@_的第一个数据元素传递。如果您尝试打印$_[0],则会得到ARRAY:6E43832之类的内容,表示数据元素是一个数组,并且它位于内存中。

现在,您可以使用ref函数查看一段数据是否为引用及其引用类型:

 sub foo {
     foreach my $item (@_) {

        if (ref $item eq 'ARRAY') {
           print "This element is a reference to an array\n";
        }
        elsif (ref $item eq 'HASH') {
           print "This element is a reference to a hash\n";
        }
        elsif (ref $item) {   #Mysterious Moe Reference
            print "This element is a reference to a " . lc (ref $item) . "\n";
        }
        else {
            print "This element is a scalar and it's value is '$item'\n";
        }
    }
}

当然,您对数组的引用可能是一个数组,其中包含对包含对数组的引用的哈希的引用,依此类推。 Perl附带了一个名为Data::Dumper的模块(您可以使用perldoc查看有关它的信息),该模块将打印出整个数据结构。

这就是面向对象Perl的工作方式,因此在Perl数据中嵌入其他Perl数据结构的引用确实很常见。

现在,只需使用基本的Perl及其工作原理。然后,开始查看various tutorials中关于Perl referencesPerldoc