use*_*084 1 perl hash parameter-passing
下面是一个小子程序,通过传递两个散列(每个散列包含 x 和 y 坐标)来计算两点之间的距离。我在调用子函数的行上收到“语法错误接近]{”致命错误。昨天刚开始使用 Perl,不太确定我在做什么。如何将两个哈希值传递给子函数以返回值?尝试过但没有取得多大成功,并且不确定我需要做什么(希望可以参考外部链接)。
%dot1 = ('x'=>5, 'y'=>6);
%dot2 = ('x'=>7, 'y'=>8);
sub dist {
my (%hash1) = @_[0];
my (%hash2) = @_[1];
$dist = ((@_[0]{'x'}-@_[1]{'x'})**2 + (@_[0]{'y'}-@_[1]{'y'})**2)**0.5;
}
$D = dist(\%dot1,\%dot2);
Run Code Online (Sandbox Code Playgroud)
首先也是最重要的,您应该以以下方式开始每个文件
use strict;
use warnings;
Run Code Online (Sandbox Code Playgroud)
这可以让 Perl 捕获代码中最明显的错误。
这部分大部分都很好,但是在use strict
Perl 下会抱怨%dot1
并且%dot2
未声明(如果没有strict
它们将隐式全局,这通常不是您想要的):
%dot1 = ('x'=>5, 'y'=>6);
%dot2 = ('x'=>7, 'y'=>8);
Run Code Online (Sandbox Code Playgroud)
将其更改为
my %dot1 = ('x'=>5, 'y'=>6);
my %dot2 = ('x'=>7, 'y'=>8);
Run Code Online (Sandbox Code Playgroud)
电话
$D = dist(\%dot1,\%dot2);
Run Code Online (Sandbox Code Playgroud)
有同样的问题: 应该是
my $D = dist(\%dot1,\%dot2);
Run Code Online (Sandbox Code Playgroud)
它的作用是将引用传递给sub%dot1
和sub 。%dot2
dist
my (%hash1) = @_[0];
Run Code Online (Sandbox Code Playgroud)
这一行没有多大意义:是一个列表切片,返回与索引对应的@_[0]
元素列表。换句话说,它是一个单元素切片,最好写为,直接访问单个元素。@_
0
$_[0]
但无论哪种情况,将单个元素分配给哈希都是没有意义的。Perl 会将其解释为键并将相应的值设置为undef
。您的调用\%dot1
作为第一个参数传递,$_[0]
对哈希的引用也是如此。通过使用它作为散列键,Perl 会将其转换为字符串,产生类似"HASH(0x0075ADD40)"
.
此时您的选择是取消引用该引用并制作副本:
my %hash1 = %{ $_[0] }; # effectively performs %hash1 = %dot1
Run Code Online (Sandbox Code Playgroud)
或者保留引用并在每次需要访问哈希时取消引用它:
my $hashref1 = $_[0]; # $hashref1->{foo} accesses $dot1{foo} directly
Run Code Online (Sandbox Code Playgroud)
$dist = ((@_[0]{'x'}-@_[1]{'x'})**2 + (@_[0]{'y'}-@_[1]{'y'})**2)**0.5;
Run Code Online (Sandbox Code Playgroud)
这里有几个问题。首先,您不需要(隐式全局)变量$dist
。您只想从 sub 返回一个值,这可以通过return
. 那么,如上所述,@_[0]
和@_[1]
应该分别是$_[0]
和$_[1]
。修复我们得到的
return (($_[0]{'x'} - $_[1]{'x'}) ** 2 + ($_[0]{'y'} - $_[1]{'y'}) ** 2) ** 0.5;
Run Code Online (Sandbox Code Playgroud)
这确实有效($_[0]{'x'}
是 的语法糖$_[0]->{'x'}
,即该表达式取消引用存储在中的哈希引用$_[0]
以达到'x'
的键%dot1
)。
但我们根本没有使用刚刚创建的变量。根据您想要走的路,您应该替换$_[0]{foo}
为$hash1{foo}
or $hashref1->{foo}
(以及类似的$_[1]
and %hash2
/ $hashref2
)。
最后,** 0.5
我们可以使用sqrt
.
我是这样写的:
use strict;
use warnings;
sub dist {
my ($p1, $p2) = @_;
return sqrt(($p1->{x} - $p2->{x}) ** 2 + ($p1->{y} - $p2->{y}) ** 2);
}
my %dot1 = (x => 5, y => 6);
my %dot2 = (x => 7, y => 8);
my $D = dist(\%dot1, \%dot2);
print "Result: $D\n";
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1701 次 |
最近记录: |