Я недавно добавил cartesian
функцию к List :: Gen :
cartesian CODE LIST_of_ARRAYREF
cartesian
вычисляет декартово произведение любого числа ссылок на массивы, каждый из которых может иметь любой размер. возвращает генератор
use List::Gen 'cartesian';
my $product = cartesian {$_[0] . $_[1]} [qw/a b/], [1, 2];
print "@$product"; # 'a1 a2 b1 b2'
Возвращенный «генератор» - это ленивый связанный массив, который будет генерировать значения при запросе их. Существуют также итерационные и другие методы доступа:
my $pairs = cartesian {@_} [qw/$ @ %/], ['a'..'z'], [1 .. 3];
while (my @tuple = $pairs->next) { # $pairs->reset; #$pairs->index = 5; ...
print @tuple, ', ';
}
# $a1, $a2, $a3, $b1, $b2, $b3, $c1, $c2, $c3, $d1, $d2, $d3, $e1 ...
Я не знаю, насколько большими будут наборы, с которыми вы будете работать, но преимущество использования вышеуказанного подхода заключается в том, что требования к хранилищу для генератора остаются O(1)
my $digits = cartesian {join '' => @_} ([0..9]) x 10;
say for @$digits[10**9 - 3 .. 10**9 + 3];
# 0999999998
# 0999999999
# 1000000000
# 1000000001
# 1000000002
# 1000000003
, который вычисляет только 6 элементов набора и ничего не хранит.
Как видно из примеров, возвращаемое значение cartesian
само по себе является объектом-генератором, но последующие возвращаемые значения этого объекта - это то, что возвращает coderef, переданный cartesian
. Так что если вам нужны ссылки на массивы, это просто: cartesian {\@_} ...
Кроме того, какую дополнительную работу вам пришлось проделать, чтобы справиться с благословенной ссылкой? Благословенный массив по-прежнему является массивом во всех смыслах, за исключением того, что вернет ref
. Если вы пишете логику переключения на основе ссылочного типа, Scalar::Util
'reftype
- это то, что вы должны использовать.