Я сталкиваюсь с этим все время, и я никогда не уверен, каким образом атаковать это. Ниже приведены два метода обработки некоторых фактов сезона.
Я пытаюсь выяснить, использовать ли метод 1 или 2, и каковы плюсы и минусы каждого, особенно большого количества фактов.
methodone
кажется расточительным, поскольку факты доступны, зачем создавать их список (особенно большой список). Это также должно иметь последствия для памяти, если список достаточно велик? И он не использует естественную возможность возврата в Прологе.
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').