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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With