自删除数组元素(一旦它们变得未定义)

时间:2021-01-09 14:21:34

I have a Perl script generating an array of weak references to objects. Once one of these objects goes out of scope, the reference to it in the array will become undefined.

我有一个Perl脚本生成一个对象的弱引用数组。一旦其中一个对象超出范围,数组中对它的引用将变为未定义。

ex (pseudo code):

ex(伪代码):

# Imagine an array of weak references to objects
my @array = ( $obj1_ref, $obj2_ref, $obj3_ref );

# Some other code here causes the last strong reference
# of $obj2_ref to go out of scope.

# We now have the following array
@array = ( $obj1_ref, undef, $obj3_ref )

Is there a way to make the undefined reference automatically remove itself from the array once it becomes undefined?

是否有一种方法可以使未定义的引用在数组未定义时自动从数组中删除?

I want @array = ($obj1_red, $obj3_ref ).

我想要@array =($ obj1_red,$ obj3_ref)。

EDIT:

I tried this solution and it didn't work:

我尝试了这个解决方案但它不起作用:

#!/usr/bin/perl
use strict;
use warnings;

{
    package Object;
    sub new { my $class = shift; bless({ @_ }, $class) }
}

{
    use Scalar::Util qw(weaken);
    use Data::Dumper;

    my $object = Object->new();

    my $array;
    $array = sub { \@_ }->( grep defined, @$array );

    {
        my $object = Object->new();
        @$array = ('test1', $object, 'test3');
        weaken($array->[1]);
        print Dumper($array);
    }

    print Dumper($array);

Output:

输出:

$VAR1 = [
          'test1',
          bless( {}, 'Object' ),
          'test3'
        ];
$VAR1 = [
          'test1',
          undef,
          'test3'
        ];

The undef is not removed from the array automatically.

undef不会自动从阵列中删除。

Am I missing something?

我错过了什么吗?

EDIT 2:

I also tried removing undefined values from the array in the DESTROY method of the object, but that doesn't appear to work either. It appears that since the object is still technically not "destroyed" yet, the weak references are still defined until the DESTROY method is completed...

我也尝试在对象的DESTROY方法中从数组中删除未定义的值,但这似乎也不起作用。看来,由于对象在技术上仍然没有被“破坏”,所以在DESTROY方法完成之前,仍然会定义弱引用...

2 个解决方案

#1


1  

No, there isn't, short of using a magical (e.g. tied) array.

不,没有,没有使用魔法(例如绑定)阵列。

If you have a reference to an array instead of an array, you can use the following to filter out the undefined element efficiently without "hardening" any of the references.

如果您对数组而不是数组有引用,则可以使用以下内容有效地过滤掉未定义的元素,而不会“强化”任何引用。

$array = sub { \@_ }->( grep defined, @$array );

This doesn't copy the values at all, in fact. Only "C pointers" get copied.

事实上,这根本不会复制值。只有“C指针”被复制。

#2


0  

Perl won't do this for you automatically. You have a couple of options. The first is to clean it yourself whenever you use it:

Perl不会自动为您执行此操作。你有几个选择。首先是每次使用时自行清洁:

my @clean = grep { defined $_ } @dirty;

Or you could create a tie'd array and add that functionality to the FETCH* and POP hooks.

或者您可以创建一个tie'd数组并将该功能添加到FETCH *和POP挂钩。

#1


1  

No, there isn't, short of using a magical (e.g. tied) array.

不,没有,没有使用魔法(例如绑定)阵列。

If you have a reference to an array instead of an array, you can use the following to filter out the undefined element efficiently without "hardening" any of the references.

如果您对数组而不是数组有引用,则可以使用以下内容有效地过滤掉未定义的元素,而不会“强化”任何引用。

$array = sub { \@_ }->( grep defined, @$array );

This doesn't copy the values at all, in fact. Only "C pointers" get copied.

事实上,这根本不会复制值。只有“C指针”被复制。

#2


0  

Perl won't do this for you automatically. You have a couple of options. The first is to clean it yourself whenever you use it:

Perl不会自动为您执行此操作。你有几个选择。首先是每次使用时自行清洁:

my @clean = grep { defined $_ } @dirty;

Or you could create a tie'd array and add that functionality to the FETCH* and POP hooks.

或者您可以创建一个tie'd数组并将该功能添加到FETCH *和POP挂钩。