Лично я предпочитаю рекурсию сгибу в Erlang (в отличие от других языков, например, Haskell).Я не вижу сгиб более читабельным, чем рекурсия.Например:
fsum(L) -> lists:foldl(fun(X,S) -> S+X end, 0, L).
или
fsum(L) ->
F = fun(X,S) -> S+X end,
lists:foldl(F, 0, L).
против
rsum(L) -> rsum(L, 0).
rsum([], S) -> S;
rsum([H|T], S) -> rsum(T, H+S).
Кажется больше кода, но это довольно простой и идиоматичный Erlang.Использование сгиба требует меньше кода, но разница становится все меньше и меньше с большей полезной нагрузкой.Представьте, что мы хотим фильтр и отображаем нечетные значения в их квадрате.
lcfoo(L) -> [ X*X || X<-L, X band 1 =:= 1].
fmfoo(L) ->
lists:map(fun(X) -> X*X end,
lists:filter(fun(X) when X band 1 =:= 1 -> true; (_) -> false end, L)).
ffoo(L) -> lists:foldr(
fun(X, A) when X band 1 =:= 1 -> [X|A];
(_, A) -> A end,
[], L).
rfoo([]) -> [];
rfoo([H|T]) when H band 1 =:= 1 -> [H*H | rfoo(T)];
rfoo([_|T]) -> rfoo(T).
Здесь перечисление выигрывает в понимании, но на втором месте рекурсивная функция, а складная версия уродлива и менее читаема.
Инаконец, неверно, что сложение происходит быстрее, чем рекурсивная версия, особенно при компиляции в собственный (HiPE) код.
Редактировать : я добавляю сложенную версию с fun в переменной по запросу:
ffoo2(L) ->
F = fun(X, A) when X band 1 =:= 1 -> [X|A];
(_, A) -> A
end,
lists:foldr(F, [], L).
Я не понимаю, как это более читабельно, чем rfoo/1
, и я обнаружил, что манипулирование с аккумулятором особенно сложнее и менее очевидно, чем прямая рекурсия.Это еще более длинный код.