问:我们怎样才能摆脱SICStus Prolog中的maplist
开销(如 SWI 的开销) ?apply_macros
A:目标扩展。
首先,我们定义我们需要的辅助谓词。下面我们使用 SICStus Prolog 4.5.0。
:- 模块(maplist_macros, [maplist/2, maplist/3, maplist/4, maplist/5, maplist/6, maplist/7, maplist/8, maplist/9])。 :- meta_predicate maplist(1,?), maplist(2,?,?), maplist(3,?,?,?), maplist(4,?,?,?,?), maplist(5,?,? ,?,?,?), maplist(6,?,?,?,?,?,?), maplist(7,?,?,?,?,?,?,?), maplist(8,?, ?,?,?,?,?,?,?)。 :- use_module(library(lists), [append/2, same_length/2])。 :- 使用模块(库(ordsets))。 callable_arglists_appended(C0, New, C1) :- C0 =.. Parts0, 附加([零件 0|新],零件 1), C1 =.. 零件 1。 :- 动态 expand_goal_aux/1。 my_expand_goal(目标,扩展):- 断言((expand_goal_aux(目标):-目标)), 收回((expand_goal_aux(目标):- Expanded0)), strip_module(扩展0,_,扩展)。 strip_module(MGoal_0,模块,Goal_0):- aux_strip_module(MGoal_0,Goal_0,lambda,模块)。% 拉姆达?! aux_strip_module(MG_0,G_0,M0,M):- (非变量(MG_0), MG_0 = (M1:MG1_0) -> aux_strip_module(MG1_0,G_0,M1,M) ; MG_0 = G_0, M0 = M )。 :- 动态 maplist_aux_count/1。 maplist_aux_count(0)。
现在进入目标扩展:
% 生成专门的 `maplist/N' 目标扩展(目标0,_Layout0,FromModule,FromModule:目标,[]):- 目标0 =.. [地图列表,Rel0 | 参数], 可调用(Rel0), 参数 = [_|_], !, % get count # of aux preds 到目前为止生成并增加它 收回(maplist_aux_count(C)), C1 是 C+1, 断言(maplist_aux_count(C1)), % 构建谓词函子 `AuxPred' number_chars(C, C_chars), atom_chars(C_atom, C_chars), atom_concat(maplist_aux_, C_atom, AuxPred), % 例如, maplist_aux_3 % 强制所有相关列表具有相同的长度 列表:maplist(same_length(Args), [Vars_E,Nils]), 列表:maplist(列表:cons,Vars_E,Vars_Es,Vars_E_Es), 列表:maplist(=([]),尼尔斯), % 在正确的模块中扩展目标(`FromModule') strip_module(Rel0,_,Rel1), callable_arglists_appended(Rel1, [Vars_E], Rel2), my_expand_goal(FromModule:Rel2, Rel), % 找出需要穿线的变量 term_variables(Rel, Vars_Schema), list_to_ord_set(Vars_Schema, VSet_Schema), list_to_ord_set(Vars_E, VSet_E), ord_subtract(VSet_Schema, VSet_E, VSet_Actual), % 使用适当的参数构建新谓词的调用 callable_arglists_appended(AuxPred, [Args,VSet_Actual], 目标), % 被调用者子句(新谓词) callable_arglists_appended(AuxPred, [Nils, VSet_Actual], Head0), % 事实 callable_arglists_appended(AuxPred, [Vars_E_Es,VSet_Actual], Head1), % 规则 callable_arglists_appended(AuxPred, [Vars_Es, VSet_Actual], Rec1), % % 将生成的子句转储到文件中 atom_concat('/tmp/x', C_atom, FileName), % TODO: 获取实际的 tmpfilnam 打开(文件名,写,S), 描绘子句(S,(Head0 :- true)), 描绘子句(S,(Head1:- Rel,Rec1)), 关闭(S), % 在适当的模块中编译临时文件 编译(从模块:文件名)。
到目前为止一切都很好;)所以这就是问题所在......
如何确保目标扩展变体与它替换的谓词完全相同?
(我有一种预感,它不是,但我不能完全确定它......)
简单示例用例 #1
allequal(Xs) :- maplist(=(_), Xs).
变成
allequal(A) :- maplist_aux_0(A, _).
maplist_aux_0([], _).
maplist_aux_0([A|B], C) :- C=A, maplist_aux_0(B, C).