1

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

#!/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 版本的代码。

4

3 回答 3

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以了解有关参考的所有信息。

于 2012-08-12T20:50:22.080 回答
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);

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

您的子程序很好,但使用一些事实上的标准将帮助其他人遵循您的程序。首先约定是如果有错误子程序会返回undef,这样你就可以写

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

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

稍微整理一下并使用unlessand ifas 语句修饰符就可以做到这一点

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

print somme_prod(2, 2, 3, 7);
于 2012-08-12T22:10:07.257 回答
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!

在这种情况下,您不会传入@arrayinto的值foo。相反,对数组的引用作为 的第一个数据元素传递@_。如果您尝试 print out $_[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 及其工作原理。然后,开始查看Perldoc中有关Perl 引用各种教程

于 2012-08-12T23:46:14.950 回答