我刚开始使用在线教程开始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版本的代码。
答案 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
表示错误
稍微整理一下,并使用unless
和if
作为语句修饰符给出了这个
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 references的Perldoc。