perl 如何检测数组中重复的代码引用?

djmepvbi  于 2023-08-06  发布在  Perl
关注(0)|答案(3)|浏览(99)

我正在调试我写的一些复杂代码(即:我还在写)。在某个时刻,有一个带有代码引用(基本上是闭包)的数组,动态填充。数组中不应该有任何重复项,但却有!
因此,我想在程序中添加检查,以便在一些不必要的影响使调试变得更加困难之前(这些闭包操作数据,最后数据不是它应该是的)尽早检测。
例如,这是调试器的输出:

DB<0> x FORMATTERS
0  CODE(0x1f6d5e0)
   -> &Class::__ANON__[lib/Class.pm:284] in lib/Class.pm:279-284
1  CODE(0x1f6dc28)
   -> &Class::__ANON__[lib/Class.pm:284] in lib/Class.pm:279-284
2  CODE(0x1f6d5e0)
   -> REUSED_ADDRESS
3  CODE(0x1f6d5e0)
   -> REUSED_ADDRESS
4  CODE(0x1f6dc28)
   -> REUSED_ADDRESS
5  CODE(0x1f6d5e0)
   -> REUSED_ADDRESS
6  CODE(0x1f6d5e0)
   -> REUSED_ADDRESS
7  CODE(0x1f6dc28)
   -> REUSED_ADDRESS
8  CODE(0x231c800)
   -> &Class::__ANON__[lib/Class.pm:284] in lib/Class.pm:279-284
9  CODE(0x1f6d5e0)
   -> REUSED_ADDRESS
10  CODE(0x1f6dc28)
   -> REUSED_ADDRESS

字符串
请注意,三个 * 不同 * 的项引用相同的“lib/Class.pm:279-284”,但这是可以的,但那些“REUSED_ADDRESS”项不是。
显然调试器可以检测到重复的地址;当我试图实现一个测试时,我的第一选择是散列,但是你不能真的使用引用作为散列键。
那么,如何有效地测试数组中的重复引用呢?

# sketch; untested code
my @a; # array with unknown contents
my $duplicate = 0;
for (my $i = 0; $i <= $#a; ++$i) {
    for (my $j = 0; $j <= $#a; ++$j) {
        next if ($j >= $i);
        ++$duplicate
            if ($a[$i] == $a[$j]);
    }
}

pjngdqdw

pjngdqdw1#

你能用这个代码作为哈希键吗?
例如,在

use strict;
use warnings;

my $sub1 = sub {};
my $sub2 = sub {};
my @testarray = ($sub1, $sub2, $sub1);
my %testhash;
foreach (@testarray) {
    if (defined $testhash{$_}) {
        print "Duplicate = $_\n";
    } else {
        $testhash{$_} = 1;
    }
}

字符串

fafcakar

fafcakar2#

最后,我使用这段代码来确定数组中的任何重复项(可以编写更复杂的代码来指示实际的重复项并对每个重复项进行计数):

#!/usr/bin/perl
require 5.018_000;

use strict;
use warnings;

# return whether there are duplicates in array
sub has_duplicates(@)
{
    use integer;
    for (my $i = 0; $i <= $#_; ++$i) {
        for (my $j = 0; $j <= $#_; ++$j) {
            last if ($j >= $i);
            return 1
                if (defined $_[$i] && defined $_[$j] && $_[$i] == $_[$j]);
        }
    }
    return 0;
}

my $sub1 = sub {};
my $sub2 = sub {};
my @array = ($sub1, $sub2, $sub1);

print "array has ", (has_duplicates(@array) ? '' : 'no '), "duplicates\n";

字符串

wlwcrazw

wlwcrazw3#

代码引用numify到sub的地址,所以numifications是唯一的。[1]您的代码依赖于此。但这也意味着我们可以利用

use List::Util qw( uniqint );  # 1.55

@code_refs = uniqint @code_refs;

字符串
类似地,我们也可以使用效率较低的字符串比较。

use List::Util qw( uniq );  # 1.45

@code_refs = uniq @code_refs;


1.我认为从技术上讲,祝福代码引用是可能的,因此可以重载它们的numification。我从没听说过。

相关问题