Все приведенные примеры имеют O (2 ^ N) сложность памяти, потому что они возвращают весь результат (первый пример).Два последних примера используют регулярную рекурсию, чтобы стек повышался.Ниже код, который является модификацией и компиляцией примеров, будет делать то, что вы хотите:
subsets(Lst) ->
N = length(Lst),
Max = trunc(math:pow(2, N)),
subsets(Lst, 0, N, Max).
subsets(Lst, I, N, Max) when I < Max ->
_Subset = [lists:nth(Pos+1, Lst) || Pos <- lists:seq(0, N-1), I band (1 bsl Pos) =/= 0],
% perform some actions on particular subset
subsets(Lst, I+1, N, Max);
subsets(_, _, _, _) ->
done.
В приведенном выше фрагменте используется хвостовая рекурсия, которая оптимизирована компилятором Erlang и преобразована в простую итерацию под прикрытием.Рекурсия может быть оптимизирована таким образом, только если рекурсивный вызов является последним в потоке выполнения функции.Также обратите внимание, что каждое сгенерированное Подмножество может использоваться вместо комментария, и оно будет забыто (сборщик мусора) сразу после этого.Благодаря этому ни стек, ни куча не будут расти, но вам также придется выполнять операции над подмножествами один за другим, так как нет окончательного результата, содержащего их все.
Мой код использует те же имена для аналогичных переменных, как впримеры, чтобы было легче сравнить их обоих.Я уверен, что это может быть улучшено для производительности, но я только хочу показать идею.