Я все время сталкиваюсь с этим, и я никогда не знаю, каким путем его атаковать. Ниже приведены два метода обработки некоторых сезонных фактов.Каковы плюсы и минусы использования ручной итерации списка против рекурсии через сбой
Что я пытаюсь решить, следует ли использовать метод 1 или 2, и каковы плюсы и минусы каждого из них, особенно большое количество фактов.
methodone
Кажется расточительным, поскольку факты доступны, зачем беспокоиться о создании списка из них (особенно большого списка). Это также должно иметь последствия для памяти, если список достаточно велик? И он не использует преимущества функции Prolog's backtracking.
methodtwo
использует возможность возврата, чтобы сделать рекурсию для меня, и я бы предположил, что она будет гораздо более эффективной с точки зрения памяти, но насколько хороша практика программирования? Это, возможно, уродливее, чтобы следовать, и могут ли быть какие-либо другие побочные эффекты?
Одна проблема, которую я вижу, заключается в том, что каждый раз, когда вызывается fail
, мы теряем способность передавать что-либо обратно вызывающему предикату, например. если это было methodtwo(SeasonResults)
, так как мы постоянно прерываем предикат. Таким образом, methodtwo
нужно будет утверждать факты для хранения состояния.
Предположительно (?) Метод 2 будет быстрее, так как он не обрабатывает (большой) список?
Я мог представить, что если бы у меня был список, то methodone
был бы способ пойти .. или это всегда так? Может ли смысл в любых условиях утверждать список фактов, используя methodone
, затем обрабатывать их с использованием метода два? Полное безумие?
Но с другой стороны, я читал, что утверждение фактов - очень «дорогой» бизнес, поэтому обработка списка может быть способом, даже для больших списков?
Любые мысли? Или иногда лучше использовать один, а не другой, в зависимости от (какой) ситуации? например. для оптимизации памяти используйте метод 2, включая утверждение фактов и, для метода использования скорости 1?
season(spring).
season(summer).
season(autumn).
season(winter).
% Season handling
showseason(Season) :-
atom_length(Season, LenSeason),
write('Season Length is '), write(LenSeason), nl.
% -------------------------------------------------------------
% Method 1 - Findall facts/iterate through the list and process each
%--------------------------------------------------------------
% Iterate manually through a season list
lenseason([]).
lenseason([Season|MoreSeasons]) :-
showseason(Season),
lenseason(MoreSeasons).
% Findall to build a list then iterate until all done
methodone :-
findall(Season, season(Season), AllSeasons),
lenseason(AllSeasons),
write('Done').
% -------------------------------------------------------------
% Method 2 - Use fail to force recursion
%--------------------------------------------------------------
methodtwo :-
% Get one season and show it
season(Season),
showseason(Season),
% Force prolog to backtrack to find another season
fail.
% No more seasons, we have finished
methodtwo :-
write('Done').
спасибо - я не знал о forall() - тот ускользнул от меня. Хороший - это полезно для меня прямо сейчас. – magus
@larsmans: Но forall/2 - это, по сути, контур с отказом. Невозможно сохранить привязки от forall! Это 'forall (A, B)' ≡ '\ + \ + forall (A, B)' – false
@false: да, но с той разницей, что FDL всегда терпит неудачу, а 'forall' может на самом деле преуспеть. Для реализации цикла достаточно. –