下面是一个小子,通过传递两个包含x和y坐标的哈希来计算两点之间的距离。我在{"附近发现了#34;语法错误在调用sub的行上发生致命错误。刚刚开始使用Perl,并不完全确定我在做什么。如何将两个哈希值传递给sub以返回值?尝试this但没有取得多大成功,也不确定我需要做些什么(希望可以参考外部链接)。
%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);
答案 0 :(得分:3)
首先,您应该使用
启动每个文件use strict;
use warnings;
这使得Perl可以捕获代码中最明显的错误。
此部分基本上很好,但在use strict
下,Perl会抱怨%dot1
和%dot2
未声明(并且没有strict
它们将隐含全局,这通常是不是你想要的):
%dot1 = ('x'=>5, 'y'=>6);
%dot2 = ('x'=>7, 'y'=>8);
将其更改为
my %dot1 = ('x'=>5, 'y'=>6);
my %dot2 = ('x'=>7, 'y'=>8);
电话
$D = dist(\%dot1,\%dot2);
有同样的问题:它应该是
my $D = dist(\%dot1,\%dot2);
它的作用是将对%dot1
和%dot2
的引用传递给子dist
。
my (%hash1) = @_[0];
这一行没有多大意义:@_[0]
是一个列表切片,返回对应于索引@_
的{{1}}元素列表。换句话说,它是一个单元素切片,最好写成0
,直接访问单个元素。
但在任何一种情况下,将单个元素分配给哈希都没有意义。 Perl会将其解释为键并将相应的值设置为$_[0]
。您的调用作为第一个参数传递undef
,因此\%dot1
是对哈希的引用。通过将其用作哈希键,Perl会将其转换为字符串,产生类似$_[0]
的内容。
此时您的选择是在此处取消引用引用并复制:
"HASH(0x0075ADD40)"
每次需要访问哈希值时,请保留引用并取消引用它:
my %hash1 = %{ $_[0] }; # effectively performs %hash1 = %dot1
my $hashref1 = $_[0]; # $hashref1->{foo} accesses $dot1{foo} directly
这里有一些问题。首先,您不需要(隐式全局)变量 $dist = ((@_[0]{'x'}-@_[1]{'x'})**2 + (@_[0]{'y'}-@_[1]{'y'})**2)**0.5;
。您只想从sub返回一个值,可以使用$dist
来完成。然后,如上所述,return
和@_[0]
应分别为@_[1]
和$_[0]
。修复我们得到的
$_[1]
确实有效( return (($_[0]{'x'} - $_[1]{'x'}) ** 2 + ($_[0]{'y'} - $_[1]{'y'}) ** 2) ** 0.5;
是$_[0]{'x'}
的语法糖,即此表达式取消引用存储在$_[0]->{'x'}
中的哈希引用,以达到$_[0]
的{{1}}键}})。
但我们根本没有使用我们刚创建的变量。根据您要采用的方式,您应该将'x'
替换为%dot1
或$_[0]{foo}
(以及$hash1{foo}
和$hashref1->{foo}
/ {{1} })。
最后,我们可以使用$_[1]
而不是%hash2
。
以下是我写的方式:
$hashref2
答案 1 :(得分:2)
这里有很多问题,我很害怕。
首先,您需要在代码中添加use strict
和use warnings
。这将指出许多错误。主要是您使用@array[index]
但应该使用$array[index]
的地方。您也没有声明任何变量。
修复所有这些代码给了我这个代码:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my %dot1 = ('x'=>5, 'y'=>6);
my %dot2 = ('x'=>7, 'y'=>8);
sub dist {
my (%hash1) = $_[0];
my (%hash2) = $_[1];
my $dist = (($_[0]{'x'}-$_[1]{'x'})**2 + ($_[0]{'y'}-$_[1]{'y'})**2)**0.5;
}
my $D = dist(\%dot1,\%dot2);
say $D;
这仍然无法奏效。我明白了:
$ perl twohash
Reference found where even-sized list expected at twohash line 11.
Reference found where even-sized list expected at twohash line 12.
2.82842712474619
错误是您将传递给dist()
的两个参数分配的地方。
my (%hash1) = $_[0];
my (%hash2) = $_[1];
您正在传递对哈希的引用,而不是哈希本身(并且您正确地执行此操作),但这意味着您在子例程中获得了标量,而不是哈希。所以这些行必须是:
my ($hash1) = $_[0];
my ($hash2) = $_[1];
进行这些更改后,代码现在可以运行并提供结果" 2.82842712474619"。
我只是在你的代码中指出一个更奇怪的东西 - 你将函数的参数分配给两个词法变量($hash1
和$hash2
),然后你忽略那些变量而不是直接转到@_
获取此数据。我希望你真的想要:
my $dist = (($hash1->{'x'}-$hash2->{'x'})**2 + ($hash1->{'y'}-$hash2->{'y'})**2)**0.5;
注意,我已将$_[0]{'x'}
更改为$hash1->{'x'}
,因为您引用了哈希。
总而言之,这段代码有点乱,我建议你回到你从Perl那里学到的任何书的最早章节。
答案 2 :(得分:-1)
请你试试这个:
use Data::Dumper;
my %dot1 = ('x'=>5, 'y'=>6);
my %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);
print $D;