我一直遇到这种情况,我永远不知道用哪种方法来攻击它。以下是处理某些季节事实的两种方法。
我正在努力解决的是使用方法1还是2,以及每种方法的优缺点,尤其是大量的事实。
methodone
似乎很浪费,因为事实是可用的,为什么还要建立一个列表(尤其是一个大列表)。如果列表足够大,这也一定会影响内存?而且它没有利用 Prolog 的自然回溯功能。
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').