Eric Strom
Eric Strom

Reputation: 40152

How do I concatenate arrays of aliases in Perl?

How do you concatenate arrays of aliases in Perl such that the resulting array also contains aliases?

The solution that I came up with is:

my ($x, $y, $z) = 1 .. 3;

my $a1 = sub {\@_}->($x);

my $a2 = sub {\@_}->($y, $z);

my $a3 = sub {\@_}->(@$a1, @$a2);

say "@$a3";  # 1 2 3

$_++ for $x, $y, $z;

say "@$a3";  # 2 3 4

What I am not crazy about is that to create $a3 I have to completely unpack $a1 and $a2. For short arrays this isn't a problem, but as the data grows larger, it means that all array operations on aliased arrays are O(n), including traditionally O(1) operations like push or unshift.

Data::Alias could help, but it doesn't work with the latest versions of Perl. Array::RefElem contains wrappers around the api primitives av_store and av_push which can be used to implement this functionality. So something like this could work:

sub alias_push (\@@) {
    if (eval {require Array::RefElem}) {
       &Array::RefElem::av_push($_[0], $_) for @_[1 .. $#_]
    } else {
       $_[0] = sub {\@_}->(@{$_[0]}, @_[1 .. $#_])
    }
}

I am interested to know if there are any other ways. Particularly if there are any other ways using only the core modules.

Upvotes: 6

Views: 269

Answers (1)

brian d foy
brian d foy

Reputation: 132896

Is this one of the cases where you might want a linked list in Perl? Steve Lembark has a talk about the various cases where people should reconsider rolling and unrolling arrays.

I'm curious why you have to do things this way though. Not that I suspect anything odd; I'm just curious about the problem.

Upvotes: 1

Related Questions