3

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.

indexless
  • 389
  • 3
  • 11
  • If `$ref` is a reference, why don't you just call `f($ref)`? For a list, you can just `f($_) for @a`. – choroba Jan 23 '12 at 13:08
  • 1
    @indexless : If this has something to do with `XML::LibXML` then please say so. – Zaid Jan 23 '12 at 13:16
  • @Zaid Not really, now It has something to DBI module - I wish to transfer the list of values to ->execute() method, but that list is containing the references to values to be inserted. – indexless Jan 23 '12 at 13:55
  • @choroba I've pointed that `f` is the package method, which accepts list of values, so I've to provide it with list of dereferenced scalars. – indexless Jan 23 '12 at 14:02

1 Answers1

3

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);
zgpmax
  • 2,777
  • 15
  • 22
  • Thank you! Great answer, and the package seems to be very nice, I'll learn them. (I'm sitting under Mac OS X, not Ubuntu, however Data::Alias also presents in MacPorts, so no needs to install it from CPAN, either). – indexless Jan 23 '12 at 13:47
  • Data::Alias provides the `deref` function, which is exactly I was seeking for. Thank you again. – indexless Jan 23 '12 at 16:43
  • @indexless: Good call. I've updated the answer to use Data::Alias::deref – zgpmax Jan 23 '12 at 18:20