The task is to transfer a list of huge strings to subroutibe, but avoiding their copying on transfer. Say I have a reference named $ref
pointing to the very large string. Also let's have f($)
subroutine accepting a single argument. There are no problem to transfer this string to f
:
f($$ref); # data pointed by $ref is not copied to temporary value here
Really I have not a single string, but list of them, let's assign them to @a
:
my @a = ($ref_1, $ref_2, $ref_3, ...);
Now the problem would be solved by
f(map {$$_} @a);
but map
does copy every dereferenced item from @a
, and then transfer those copied instances to f
.
I have no control on f
since it actually is the method from CPAN module.
So is there possible to solve the task? Much thanks in advance.
Yes, 'map' can be a bit annoying in the way it always copies.
You can dereference a all elements from entire list into an array, without copying, using Data::Alias::deref.
Assuming @a
is an array of references, and you want to call a function f()
with an argument list which is the result of dereferencing those references, then you can do
use Data::Alias qw( alias deref );
f(deref @a);
(Note that Data::Alias exists as a distro module for (for example) Ubuntu (libdata-alias-perl), so you should be able to use it even if you can't use CPAN directly.)
In fact, if you're dealing with a lot of large string objects and minimising copying is a concern, you might want to use Data::Alias more extensively. In fact, once you have Data::Alias in your programming arsenal, you might find you don't need to store the data in your array as references at all.
Say, your data comes to you one (huge) value at a time, and you want to put those values into an array. Whereas you might currently do
push @a, \$value;
you could change that to
alias push @a, $value;
If you have two lists (of huge elements) that you want to make into one big array, you can do this
alias my @one_big_array = (@a, @b);