Perl: перенос списка огромных строк в подпрограмму без их копирования - PullRequest
3 голосов
/ 23 января 2012

Задача состоит в том, чтобы передать список огромных строк в подруби, но избегая их копирования при передаче. Скажем, у меня есть ссылка с именем $ref, указывающая на очень большую строку. Также давайте подпрограмму f($), принимающую один аргумент. Нет проблем с переносом этой строки в f:

f($$ref); # data pointed by $ref is not copied to temporary value here

На самом деле у меня нет ни одной строки, но есть список их, давайте присвоим их @a:

my @a = ($ref_1, $ref_2, $ref_3, ...);

Теперь проблема будет решена с помощью

f(map {$$_} @a);

но map делает копирование каждого разыменованного элемента из @a, а затем переносит эти скопированные экземпляры в f.

У меня нет контроля над f, поскольку на самом деле это метод из модуля CPAN.

Так есть ли возможность решить задачу? Большое спасибо заранее.

1 Ответ

3 голосов
/ 23 января 2012

Да, «карта» может немного раздражать, потому что она всегда копирует.

Вы можете разыменовать все элементы из всего списка в массив без копирования, используя Data :: Alias ​​:: deref .

Предполагая, что @a является массивом ссылок, и вы хотите вызвать функцию f() со списком аргументов, который является результатом разыменования этих ссылок, тогда вы можете сделать

use Data::Alias qw( alias deref );

f(deref @a);

(Обратите внимание, что Data :: Alias ​​ существует как модуль дистрибутива для (например) Ubuntu (libdata-alias-perl), поэтому вы должны иметь возможность использовать его, даже если вы не можете использовать CPAN напрямую.)

На самом деле, если вы имеете дело с большим количеством крупных строковых объектов и минимизация копирования является проблемой, вы можете использовать Data :: Alias ​​более широко. Фактически, если в вашем арсенале программирования есть Data :: Alias, вы можете обнаружить, что вам вообще не нужно хранить данные в вашем массиве как ссылки.

Скажем, ваши данные приходят вам по одному (огромному) значению за раз, и вы хотите поместить эти значения в массив. В то время как вы могли бы в настоящее время сделать

push @a, \$value;

Вы можете изменить это на

alias push @a, $value;

Если у вас есть два списка (из огромных элементов), которые вы хотите объединить в один большой массив, вы можете сделать это

alias my @one_big_array = (@a, @b);
...